1 /*
2 +----------------------------------------------------------------------+
3 | Zend OPcache |
4 +----------------------------------------------------------------------+
5 | Copyright (c) The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | https://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@php.net> |
16 | Zeev Suraski <zeev@php.net> |
17 | Stanislav Malyshev <stas@zend.com> |
18 | Dmitry Stogov <dmitry@php.net> |
19 +----------------------------------------------------------------------+
20 */
21
22 #include <time.h>
23
24 #include "php.h"
25 #include "ZendAccelerator.h"
26 #include "zend_API.h"
27 #include "zend_shared_alloc.h"
28 #include "zend_accelerator_blacklist.h"
29 #include "php_ini.h"
30 #include "SAPI.h"
31 #include "zend_virtual_cwd.h"
32 #include "ext/standard/info.h"
33 #include "ext/standard/php_filestat.h"
34 #include "ext/date/php_date.h"
35 #include "opcache_arginfo.h"
36
37 #if HAVE_JIT
38 #include "jit/zend_jit.h"
39 #endif
40
41 #define STRING_NOT_NULL(s) (NULL == (s)?"":s)
42 #define MIN_ACCEL_FILES 200
43 #define MAX_ACCEL_FILES 1000000
44 #define MAX_INTERNED_STRINGS_BUFFER_SIZE ((zend_long)((UINT32_MAX-PLATFORM_ALIGNMENT-sizeof(zend_accel_shared_globals))/(1024*1024)))
45 #define TOKENTOSTR(X) #X
46
47 static zif_handler orig_file_exists = NULL;
48 static zif_handler orig_is_file = NULL;
49 static zif_handler orig_is_readable = NULL;
50
validate_api_restriction(void)51 static int validate_api_restriction(void)
52 {
53 if (ZCG(accel_directives).restrict_api && *ZCG(accel_directives).restrict_api) {
54 size_t len = strlen(ZCG(accel_directives).restrict_api);
55
56 if (!SG(request_info).path_translated ||
57 strlen(SG(request_info).path_translated) < len ||
58 memcmp(SG(request_info).path_translated, ZCG(accel_directives).restrict_api, len) != 0) {
59 zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " API is restricted by \"restrict_api\" configuration directive");
60 return 0;
61 }
62 }
63 return 1;
64 }
65
ZEND_INI_MH(OnUpdateMemoryConsumption)66 static ZEND_INI_MH(OnUpdateMemoryConsumption)
67 {
68 zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
69 zend_long memsize = atoi(ZSTR_VAL(new_value));
70 /* sanity check we must use at least 8 MB */
71 if (memsize < 8) {
72 zend_accel_error(ACCEL_LOG_WARNING, "opcache.memory_consumption is set below the required 8MB.\n");
73 return FAILURE;
74 }
75 if (UNEXPECTED(memsize > ZEND_LONG_MAX / (1024 * 1024))) {
76 *p = ZEND_LONG_MAX & ~(1024 * 1024 - 1);
77 } else {
78 *p = memsize * (1024 * 1024);
79 }
80 return SUCCESS;
81 }
82
ZEND_INI_MH(OnUpdateInternedStringsBuffer)83 static ZEND_INI_MH(OnUpdateInternedStringsBuffer)
84 {
85 zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
86 zend_long size = zend_ini_parse_quantity_warn(new_value, entry->name);
87
88 if (size < 0) {
89 zend_accel_error(ACCEL_LOG_WARNING, "opcache.interned_strings_buffer must be greater than or equal to 0, " ZEND_LONG_FMT " given.\n", size);
90 return FAILURE;
91 }
92 if (size > MAX_INTERNED_STRINGS_BUFFER_SIZE) {
93 zend_accel_error(ACCEL_LOG_WARNING, "opcache.interned_strings_buffer must be less than or equal to " ZEND_LONG_FMT ", " ZEND_LONG_FMT " given.\n", MAX_INTERNED_STRINGS_BUFFER_SIZE, size);
94 return FAILURE;
95 }
96
97 *p = size;
98
99 return SUCCESS;
100 }
101
ZEND_INI_MH(OnUpdateMaxAcceleratedFiles)102 static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles)
103 {
104 zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
105 zend_long size = atoi(ZSTR_VAL(new_value));
106 /* sanity check we must use a value between MIN_ACCEL_FILES and MAX_ACCEL_FILES */
107 if (size < MIN_ACCEL_FILES) {
108 zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_accelerated_files is set below the required minimum (%d).\n", MIN_ACCEL_FILES);
109 return FAILURE;
110 }
111 if (size > MAX_ACCEL_FILES) {
112 zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES);
113 return FAILURE;
114 }
115 *p = size;
116 return SUCCESS;
117 }
118
ZEND_INI_MH(OnUpdateMaxWastedPercentage)119 static ZEND_INI_MH(OnUpdateMaxWastedPercentage)
120 {
121 double *p = (double *) ZEND_INI_GET_ADDR();
122 zend_long percentage = atoi(ZSTR_VAL(new_value));
123
124 if (percentage <= 0 || percentage > 50) {
125 zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_wasted_percentage must be set between 1 and 50.\n");
126 return FAILURE;
127 }
128 *p = (double)percentage / 100.0;
129 return SUCCESS;
130 }
131
ZEND_INI_MH(OnEnable)132 static ZEND_INI_MH(OnEnable)
133 {
134 if (stage == ZEND_INI_STAGE_STARTUP ||
135 stage == ZEND_INI_STAGE_SHUTDOWN ||
136 stage == ZEND_INI_STAGE_DEACTIVATE) {
137 return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
138 } else {
139 /* It may be only temporary disabled */
140 bool *p = (bool *) ZEND_INI_GET_ADDR();
141 if (zend_ini_parse_bool(new_value)) {
142 zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " can't be temporary enabled (it may be only disabled till the end of request)");
143 return FAILURE;
144 } else {
145 *p = 0;
146 ZCG(accelerator_enabled) = 0;
147 return SUCCESS;
148 }
149 }
150 }
151
ZEND_INI_MH(OnUpdateFileCache)152 static ZEND_INI_MH(OnUpdateFileCache)
153 {
154 if (new_value) {
155 if (!ZSTR_LEN(new_value)) {
156 new_value = NULL;
157 } else {
158 zend_stat_t buf = {0};
159
160 if (!IS_ABSOLUTE_PATH(ZSTR_VAL(new_value), ZSTR_LEN(new_value)) ||
161 zend_stat(ZSTR_VAL(new_value), &buf) != 0 ||
162 !S_ISDIR(buf.st_mode) ||
163 #ifndef ZEND_WIN32
164 access(ZSTR_VAL(new_value), R_OK | W_OK | X_OK) != 0) {
165 #else
166 _access(ZSTR_VAL(new_value), 06) != 0) {
167 #endif
168 zend_accel_error(ACCEL_LOG_WARNING, "opcache.file_cache must be a full path of accessible directory.\n");
169 new_value = NULL;
170 }
171 }
172 }
173 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
174 return SUCCESS;
175 }
176
177 #ifdef HAVE_JIT
178 static ZEND_INI_MH(OnUpdateJit)
179 {
180 if (zend_jit_config(new_value, stage) == SUCCESS) {
181 return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
182 }
183 return FAILURE;
184 }
185
186 static ZEND_INI_MH(OnUpdateJitDebug)
187 {
188 zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
189 zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name);
190
191 if (zend_jit_debug_config(*p, val, stage) == SUCCESS) {
192 *p = val;
193 return SUCCESS;
194 }
195 return FAILURE;
196 }
197
198 static ZEND_INI_MH(OnUpdateCounter)
199 {
200 zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name);
201 if (val >= 0 && val < 256) {
202 zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
203 *p = val;
204 return SUCCESS;
205 }
206 zend_error(E_WARNING, "Invalid \"%s\" setting; using default value instead. Should be between 0 and 255", ZSTR_VAL(entry->name));
207 return FAILURE;
208 }
209
210 static ZEND_INI_MH(OnUpdateUnrollC)
211 {
212 zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name);
213 if (val > 0 && val < ZEND_JIT_TRACE_MAX_CALL_DEPTH) {
214 zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
215 *p = val;
216 return SUCCESS;
217 }
218 zend_error(E_WARNING, "Invalid \"%s\" setting. Should be between 1 and %d", ZSTR_VAL(entry->name),
219 ZEND_JIT_TRACE_MAX_CALL_DEPTH);
220 return FAILURE;
221 }
222
223 static ZEND_INI_MH(OnUpdateUnrollR)
224 {
225 zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name);
226 if (val >= 0 && val < ZEND_JIT_TRACE_MAX_RET_DEPTH) {
227 zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
228 *p = val;
229 return SUCCESS;
230 }
231 zend_error(E_WARNING, "Invalid \"%s\" setting. Should be between 0 and %d", ZSTR_VAL(entry->name),
232 ZEND_JIT_TRACE_MAX_RET_DEPTH);
233 return FAILURE;
234 }
235
236 static ZEND_INI_MH(OnUpdateUnrollL)
237 {
238 zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name);
239 if (val > 0 && val < ZEND_JIT_TRACE_MAX_LOOPS_UNROLL) {
240 zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
241 *p = val;
242 return SUCCESS;
243 }
244 zend_error(E_WARNING, "Invalid \"%s\" setting. Should be between 1 and %d", ZSTR_VAL(entry->name),
245 ZEND_JIT_TRACE_MAX_LOOPS_UNROLL);
246 return FAILURE;
247 }
248
249 static ZEND_INI_MH(OnUpdateMaxTraceLength)
250 {
251 zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name);
252 if (val > 3 && val <= ZEND_JIT_TRACE_MAX_LENGTH) {
253 zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
254 *p = val;
255 return SUCCESS;
256 }
257 zend_error(E_WARNING, "Invalid \"%s\" setting. Should be between 4 and %d", ZSTR_VAL(entry->name),
258 ZEND_JIT_TRACE_MAX_LENGTH);
259 return FAILURE;
260 }
261 #endif
262
263 ZEND_INI_BEGIN()
264 STD_PHP_INI_BOOLEAN("opcache.enable" , "1", PHP_INI_ALL, OnEnable, enabled , zend_accel_globals, accel_globals)
265 STD_PHP_INI_BOOLEAN("opcache.use_cwd" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.use_cwd , zend_accel_globals, accel_globals)
266 STD_PHP_INI_BOOLEAN("opcache.validate_timestamps", "1", PHP_INI_ALL , OnUpdateBool, accel_directives.validate_timestamps, zend_accel_globals, accel_globals)
267 STD_PHP_INI_BOOLEAN("opcache.validate_permission", "0", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.validate_permission, zend_accel_globals, accel_globals)
268 #ifndef ZEND_WIN32
269 STD_PHP_INI_BOOLEAN("opcache.validate_root" , "0", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.validate_root , zend_accel_globals, accel_globals)
270 #endif
271 STD_PHP_INI_BOOLEAN("opcache.dups_fix" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.ignore_dups , zend_accel_globals, accel_globals)
272 STD_PHP_INI_BOOLEAN("opcache.revalidate_path" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.revalidate_path , zend_accel_globals, accel_globals)
273
274 STD_PHP_INI_ENTRY("opcache.log_verbosity_level" , "1" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.log_verbosity_level, zend_accel_globals, accel_globals)
275 STD_PHP_INI_ENTRY("opcache.memory_consumption" , "128" , PHP_INI_SYSTEM, OnUpdateMemoryConsumption, accel_directives.memory_consumption, zend_accel_globals, accel_globals)
276 STD_PHP_INI_ENTRY("opcache.interned_strings_buffer", "8" , PHP_INI_SYSTEM, OnUpdateInternedStringsBuffer, accel_directives.interned_strings_buffer, zend_accel_globals, accel_globals)
277 STD_PHP_INI_ENTRY("opcache.max_accelerated_files" , "10000", PHP_INI_SYSTEM, OnUpdateMaxAcceleratedFiles, accel_directives.max_accelerated_files, zend_accel_globals, accel_globals)
278 STD_PHP_INI_ENTRY("opcache.max_wasted_percentage" , "5" , PHP_INI_SYSTEM, OnUpdateMaxWastedPercentage, accel_directives.max_wasted_percentage, zend_accel_globals, accel_globals)
279 STD_PHP_INI_ENTRY("opcache.force_restart_timeout" , "180" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.force_restart_timeout, zend_accel_globals, accel_globals)
280 STD_PHP_INI_ENTRY("opcache.revalidate_freq" , "2" , PHP_INI_ALL , OnUpdateLong, accel_directives.revalidate_freq, zend_accel_globals, accel_globals)
281 STD_PHP_INI_ENTRY("opcache.file_update_protection", "2" , PHP_INI_ALL , OnUpdateLong, accel_directives.file_update_protection, zend_accel_globals, accel_globals)
282 STD_PHP_INI_ENTRY("opcache.preferred_memory_model", "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.memory_model, zend_accel_globals, accel_globals)
283 STD_PHP_INI_ENTRY("opcache.blacklist_filename" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.user_blacklist_filename, zend_accel_globals, accel_globals)
284 STD_PHP_INI_ENTRY("opcache.max_file_size" , "0" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.max_file_size, zend_accel_globals, accel_globals)
285
286 STD_PHP_INI_BOOLEAN("opcache.protect_memory" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.protect_memory, zend_accel_globals, accel_globals)
287 STD_PHP_INI_BOOLEAN("opcache.save_comments" , "1" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.save_comments, zend_accel_globals, accel_globals)
288 STD_PHP_INI_BOOLEAN("opcache.record_warnings" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.record_warnings, zend_accel_globals, accel_globals)
289
290 STD_PHP_INI_ENTRY("opcache.optimization_level" , DEFAULT_OPTIMIZATION_LEVEL , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.optimization_level, zend_accel_globals, accel_globals)
291 STD_PHP_INI_ENTRY("opcache.opt_debug_level" , "0" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.opt_debug_level, zend_accel_globals, accel_globals)
292 STD_PHP_INI_BOOLEAN("opcache.enable_file_override" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.file_override_enabled, zend_accel_globals, accel_globals)
293 STD_PHP_INI_BOOLEAN("opcache.enable_cli" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.enable_cli, zend_accel_globals, accel_globals)
294 STD_PHP_INI_ENTRY("opcache.error_log" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.error_log, zend_accel_globals, accel_globals)
295 STD_PHP_INI_ENTRY("opcache.restrict_api" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.restrict_api, zend_accel_globals, accel_globals)
296
297 #ifndef ZEND_WIN32
298 STD_PHP_INI_ENTRY("opcache.lockfile_path" , "/tmp" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.lockfile_path, zend_accel_globals, accel_globals)
299 #else
300 STD_PHP_INI_ENTRY("opcache.mmap_base", NULL, PHP_INI_SYSTEM, OnUpdateString, accel_directives.mmap_base, zend_accel_globals, accel_globals)
301 #endif
302
303 STD_PHP_INI_ENTRY("opcache.file_cache" , NULL , PHP_INI_SYSTEM, OnUpdateFileCache, accel_directives.file_cache, zend_accel_globals, accel_globals)
304 STD_PHP_INI_BOOLEAN("opcache.file_cache_only" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.file_cache_only, zend_accel_globals, accel_globals)
305 STD_PHP_INI_BOOLEAN("opcache.file_cache_consistency_checks" , "1" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.file_cache_consistency_checks, zend_accel_globals, accel_globals)
306 #if ENABLE_FILE_CACHE_FALLBACK
307 STD_PHP_INI_BOOLEAN("opcache.file_cache_fallback" , "1" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.file_cache_fallback, zend_accel_globals, accel_globals)
308 #endif
309 #ifdef HAVE_HUGE_CODE_PAGES
310 STD_PHP_INI_BOOLEAN("opcache.huge_code_pages" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.huge_code_pages, zend_accel_globals, accel_globals)
311 #endif
312 STD_PHP_INI_ENTRY("opcache.preload" , "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.preload, zend_accel_globals, accel_globals)
313 #ifndef ZEND_WIN32
314 STD_PHP_INI_ENTRY("opcache.preload_user" , "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.preload_user, zend_accel_globals, accel_globals)
315 #endif
316 #if ZEND_WIN32
317 STD_PHP_INI_ENTRY("opcache.cache_id" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.cache_id, zend_accel_globals, accel_globals)
318 #endif
319 #ifdef HAVE_JIT
320 STD_PHP_INI_ENTRY("opcache.jit" , "tracing", PHP_INI_ALL, OnUpdateJit, options, zend_jit_globals, jit_globals)
321 STD_PHP_INI_ENTRY("opcache.jit_buffer_size" , ZEND_JIT_DEFAULT_BUFFER_SIZE, PHP_INI_SYSTEM, OnUpdateLong, buffer_size, zend_jit_globals, jit_globals)
322 STD_PHP_INI_ENTRY("opcache.jit_debug" , "0", PHP_INI_ALL, OnUpdateJitDebug, debug, zend_jit_globals, jit_globals)
323 STD_PHP_INI_ENTRY("opcache.jit_bisect_limit" , "0", PHP_INI_ALL, OnUpdateLong, bisect_limit, zend_jit_globals, jit_globals)
324 STD_PHP_INI_ENTRY("opcache.jit_prof_threshold" , "0.005", PHP_INI_ALL, OnUpdateReal, prof_threshold, zend_jit_globals, jit_globals)
325 STD_PHP_INI_ENTRY("opcache.jit_max_root_traces" , "1024", PHP_INI_SYSTEM, OnUpdateLong, max_root_traces, zend_jit_globals, jit_globals)
326 STD_PHP_INI_ENTRY("opcache.jit_max_side_traces" , "128", PHP_INI_SYSTEM, OnUpdateLong, max_side_traces, zend_jit_globals, jit_globals)
327 STD_PHP_INI_ENTRY("opcache.jit_max_exit_counters" , "8192", PHP_INI_SYSTEM, OnUpdateLong, max_exit_counters, zend_jit_globals, jit_globals)
328 STD_PHP_INI_ENTRY("opcache.jit_hot_loop" , "64", PHP_INI_SYSTEM, OnUpdateCounter, hot_loop, zend_jit_globals, jit_globals)
329 STD_PHP_INI_ENTRY("opcache.jit_hot_func" , "127", PHP_INI_SYSTEM, OnUpdateCounter, hot_func, zend_jit_globals, jit_globals)
330 STD_PHP_INI_ENTRY("opcache.jit_hot_return" , "8", PHP_INI_SYSTEM, OnUpdateCounter, hot_return, zend_jit_globals, jit_globals)
331 STD_PHP_INI_ENTRY("opcache.jit_hot_side_exit" , "8", PHP_INI_ALL, OnUpdateCounter, hot_side_exit, zend_jit_globals, jit_globals)
332 STD_PHP_INI_ENTRY("opcache.jit_blacklist_root_trace" , "16", PHP_INI_ALL, OnUpdateCounter, blacklist_root_trace, zend_jit_globals, jit_globals)
333 STD_PHP_INI_ENTRY("opcache.jit_blacklist_side_trace" , "8", PHP_INI_ALL, OnUpdateCounter, blacklist_side_trace, zend_jit_globals, jit_globals)
334 STD_PHP_INI_ENTRY("opcache.jit_max_loop_unrolls" , "8", PHP_INI_ALL, OnUpdateUnrollL, max_loop_unrolls, zend_jit_globals, jit_globals)
335 STD_PHP_INI_ENTRY("opcache.jit_max_recursive_calls" , "2", PHP_INI_ALL, OnUpdateUnrollC, max_recursive_calls, zend_jit_globals, jit_globals)
336 STD_PHP_INI_ENTRY("opcache.jit_max_recursive_returns" , "2", PHP_INI_ALL, OnUpdateUnrollR, max_recursive_returns, zend_jit_globals, jit_globals)
337 STD_PHP_INI_ENTRY("opcache.jit_max_polymorphic_calls" , "2", PHP_INI_ALL, OnUpdateLong, max_polymorphic_calls, zend_jit_globals, jit_globals)
338 STD_PHP_INI_ENTRY("opcache.jit_max_trace_length" , "1024", PHP_INI_ALL, OnUpdateMaxTraceLength, max_trace_length, zend_jit_globals, jit_globals)
339 #endif
340 ZEND_INI_END()
341
342 static int filename_is_in_cache(zend_string *filename)
343 {
344 zend_string *key;
345
346 key = accel_make_persistent_key(filename);
347 if (key != NULL) {
348 zend_persistent_script *persistent_script = zend_accel_hash_find(&ZCSG(hash), key);
349 if (persistent_script && !persistent_script->corrupted) {
350 if (ZCG(accel_directives).validate_timestamps) {
351 zend_file_handle handle;
352 int ret;
353
354 zend_stream_init_filename_ex(&handle, filename);
355 ret = validate_timestamp_and_record_ex(persistent_script, &handle) == SUCCESS
356 ? 1 : 0;
357 zend_destroy_file_handle(&handle);
358 return ret;
359 }
360
361 return 1;
362 }
363 }
364
365 return 0;
366 }
367
368 static int accel_file_in_cache(INTERNAL_FUNCTION_PARAMETERS)
369 {
370 if (ZEND_NUM_ARGS() == 1) {
371 zval *zv = ZEND_CALL_ARG(execute_data , 1);
372
373 if (Z_TYPE_P(zv) == IS_STRING && Z_STRLEN_P(zv) != 0) {
374 return filename_is_in_cache(Z_STR_P(zv));
375 }
376 }
377 return 0;
378 }
379
380 static ZEND_NAMED_FUNCTION(accel_file_exists)
381 {
382 if (accel_file_in_cache(INTERNAL_FUNCTION_PARAM_PASSTHRU)) {
383 RETURN_TRUE;
384 } else {
385 orig_file_exists(INTERNAL_FUNCTION_PARAM_PASSTHRU);
386 }
387 }
388
389 static ZEND_NAMED_FUNCTION(accel_is_file)
390 {
391 if (accel_file_in_cache(INTERNAL_FUNCTION_PARAM_PASSTHRU)) {
392 RETURN_TRUE;
393 } else {
394 orig_is_file(INTERNAL_FUNCTION_PARAM_PASSTHRU);
395 }
396 }
397
398 static ZEND_NAMED_FUNCTION(accel_is_readable)
399 {
400 if (accel_file_in_cache(INTERNAL_FUNCTION_PARAM_PASSTHRU)) {
401 RETURN_TRUE;
402 } else {
403 orig_is_readable(INTERNAL_FUNCTION_PARAM_PASSTHRU);
404 }
405 }
406
407 static ZEND_MINIT_FUNCTION(zend_accelerator)
408 {
409 (void)type; /* keep the compiler happy */
410
411 REGISTER_INI_ENTRIES();
412
413 return SUCCESS;
414 }
415
416 void zend_accel_override_file_functions(void)
417 {
418 zend_function *old_function;
419 if (ZCG(enabled) && accel_startup_ok && ZCG(accel_directives).file_override_enabled) {
420 if (file_cache_only) {
421 zend_accel_error(ACCEL_LOG_WARNING, "file_override_enabled has no effect when file_cache_only is set");
422 return;
423 }
424 /* override file_exists */
425 if ((old_function = zend_hash_str_find_ptr(CG(function_table), "file_exists", sizeof("file_exists")-1)) != NULL) {
426 orig_file_exists = old_function->internal_function.handler;
427 old_function->internal_function.handler = accel_file_exists;
428 }
429 if ((old_function = zend_hash_str_find_ptr(CG(function_table), "is_file", sizeof("is_file")-1)) != NULL) {
430 orig_is_file = old_function->internal_function.handler;
431 old_function->internal_function.handler = accel_is_file;
432 }
433 if ((old_function = zend_hash_str_find_ptr(CG(function_table), "is_readable", sizeof("is_readable")-1)) != NULL) {
434 orig_is_readable = old_function->internal_function.handler;
435 old_function->internal_function.handler = accel_is_readable;
436 }
437 }
438 }
439
440 static ZEND_MSHUTDOWN_FUNCTION(zend_accelerator)
441 {
442 (void)type; /* keep the compiler happy */
443
444 UNREGISTER_INI_ENTRIES();
445 accel_shutdown();
446 return SUCCESS;
447 }
448
449 void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS)
450 {
451 php_info_print_table_start();
452
453 if (ZCG(accelerator_enabled) || file_cache_only) {
454 php_info_print_table_row(2, "Opcode Caching", "Up and Running");
455 } else {
456 php_info_print_table_row(2, "Opcode Caching", "Disabled");
457 }
458 if (ZCG(enabled) && accel_startup_ok && ZCG(accel_directives).optimization_level) {
459 php_info_print_table_row(2, "Optimization", "Enabled");
460 } else {
461 php_info_print_table_row(2, "Optimization", "Disabled");
462 }
463 if (!file_cache_only) {
464 php_info_print_table_row(2, "SHM Cache", "Enabled");
465 } else {
466 php_info_print_table_row(2, "SHM Cache", "Disabled");
467 }
468 if (ZCG(accel_directives).file_cache) {
469 php_info_print_table_row(2, "File Cache", "Enabled");
470 } else {
471 php_info_print_table_row(2, "File Cache", "Disabled");
472 }
473 #if HAVE_JIT
474 if (JIT_G(enabled)) {
475 if (JIT_G(on)) {
476 php_info_print_table_row(2, "JIT", "On");
477 } else {
478 php_info_print_table_row(2, "JIT", "Off");
479 }
480 } else {
481 php_info_print_table_row(2, "JIT", "Disabled");
482 }
483 #else
484 php_info_print_table_row(2, "JIT", "Not Available");
485 #endif
486 if (file_cache_only) {
487 if (!accel_startup_ok || zps_api_failure_reason) {
488 php_info_print_table_row(2, "Startup Failed", zps_api_failure_reason);
489 } else {
490 php_info_print_table_row(2, "Startup", "OK");
491 }
492 } else
493 if (ZCG(enabled)) {
494 if (!accel_startup_ok || zps_api_failure_reason) {
495 php_info_print_table_row(2, "Startup Failed", zps_api_failure_reason);
496 } else {
497 char buf[32];
498 zend_string *start_time, *restart_time, *force_restart_time;
499 zval *date_ISO8601 = zend_get_constant_str("DATE_ISO8601", sizeof("DATE_ISO8601")-1);
500
501 php_info_print_table_row(2, "Startup", "OK");
502 php_info_print_table_row(2, "Shared memory model", zend_accel_get_shared_model());
503 snprintf(buf, sizeof(buf), ZEND_ULONG_FMT, ZCSG(hits));
504 php_info_print_table_row(2, "Cache hits", buf);
505 snprintf(buf, sizeof(buf), ZEND_ULONG_FMT, ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses));
506 php_info_print_table_row(2, "Cache misses", buf);
507 snprintf(buf, sizeof(buf), ZEND_LONG_FMT, ZCG(accel_directives).memory_consumption-zend_shared_alloc_get_free_memory()-ZSMMG(wasted_shared_memory));
508 php_info_print_table_row(2, "Used memory", buf);
509 snprintf(buf, sizeof(buf), "%zu", zend_shared_alloc_get_free_memory());
510 php_info_print_table_row(2, "Free memory", buf);
511 snprintf(buf, sizeof(buf), "%zu", ZSMMG(wasted_shared_memory));
512 php_info_print_table_row(2, "Wasted memory", buf);
513 if (ZCSG(interned_strings).start && ZCSG(interned_strings).end) {
514 snprintf(buf, sizeof(buf), "%zu", (size_t)((char*)ZCSG(interned_strings).top - (char*)(accel_shared_globals + 1)));
515 php_info_print_table_row(2, "Interned Strings Used memory", buf);
516 snprintf(buf, sizeof(buf), "%zu", (size_t)((char*)ZCSG(interned_strings).end - (char*)ZCSG(interned_strings).top));
517 php_info_print_table_row(2, "Interned Strings Free memory", buf);
518 }
519 snprintf(buf, sizeof(buf), "%" PRIu32, ZCSG(hash).num_direct_entries);
520 php_info_print_table_row(2, "Cached scripts", buf);
521 snprintf(buf, sizeof(buf), "%" PRIu32, ZCSG(hash).num_entries);
522 php_info_print_table_row(2, "Cached keys", buf);
523 snprintf(buf, sizeof(buf), "%" PRIu32, ZCSG(hash).max_num_entries);
524 php_info_print_table_row(2, "Max keys", buf);
525 snprintf(buf, sizeof(buf), ZEND_ULONG_FMT, ZCSG(oom_restarts));
526 php_info_print_table_row(2, "OOM restarts", buf);
527 snprintf(buf, sizeof(buf), ZEND_ULONG_FMT, ZCSG(hash_restarts));
528 php_info_print_table_row(2, "Hash keys restarts", buf);
529 snprintf(buf, sizeof(buf), ZEND_ULONG_FMT, ZCSG(manual_restarts));
530 php_info_print_table_row(2, "Manual restarts", buf);
531
532 start_time = php_format_date(Z_STRVAL_P(date_ISO8601), Z_STRLEN_P(date_ISO8601), ZCSG(start_time), 1);
533 php_info_print_table_row(2, "Start time", ZSTR_VAL(start_time));
534 zend_string_release(start_time);
535
536 if (ZCSG(last_restart_time)) {
537 restart_time = php_format_date(Z_STRVAL_P(date_ISO8601), Z_STRLEN_P(date_ISO8601), ZCSG(last_restart_time), 1);
538 php_info_print_table_row(2, "Last restart time", ZSTR_VAL(restart_time));
539 zend_string_release(restart_time);
540 } else {
541 php_info_print_table_row(2, "Last restart time", "none");
542 }
543
544 if (ZCSG(force_restart_time)) {
545 force_restart_time = php_format_date(Z_STRVAL_P(date_ISO8601), Z_STRLEN_P(date_ISO8601), ZCSG(force_restart_time), 1);
546 php_info_print_table_row(2, "Last force restart time", ZSTR_VAL(force_restart_time));
547 zend_string_release(force_restart_time);
548 } else {
549 php_info_print_table_row(2, "Last force restart time", "none");
550 }
551 }
552 }
553
554 php_info_print_table_end();
555 DISPLAY_INI_ENTRIES();
556 }
557
558 static zend_module_entry accel_module_entry = {
559 STANDARD_MODULE_HEADER,
560 ACCELERATOR_PRODUCT_NAME,
561 ext_functions,
562 ZEND_MINIT(zend_accelerator),
563 ZEND_MSHUTDOWN(zend_accelerator),
564 accel_activate,
565 NULL,
566 zend_accel_info,
567 PHP_VERSION,
568 NO_MODULE_GLOBALS,
569 accel_post_deactivate,
570 STANDARD_MODULE_PROPERTIES_EX
571 };
572
573 int start_accel_module(void)
574 {
575 return zend_startup_module(&accel_module_entry);
576 }
577
578 /* {{{ Get the scripts which are accelerated by ZendAccelerator */
579 static int accelerator_get_scripts(zval *return_value)
580 {
581 uint32_t i;
582 zval persistent_script_report;
583 zend_accel_hash_entry *cache_entry;
584 struct tm *ta;
585 struct timeval exec_time;
586 struct timeval fetch_time;
587
588 if (!ZCG(accelerator_enabled) || accelerator_shm_read_lock() != SUCCESS) {
589 return 0;
590 }
591
592 array_init(return_value);
593 for (i = 0; i<ZCSG(hash).max_num_entries; i++) {
594 for (cache_entry = ZCSG(hash).hash_table[i]; cache_entry; cache_entry = cache_entry->next) {
595 zend_persistent_script *script;
596 char *str;
597 size_t len;
598
599 if (cache_entry->indirect) continue;
600
601 script = (zend_persistent_script *)cache_entry->data;
602
603 array_init(&persistent_script_report);
604 add_assoc_str(&persistent_script_report, "full_path", zend_string_dup(script->script.filename, 0));
605 add_assoc_long(&persistent_script_report, "hits", script->dynamic_members.hits);
606 add_assoc_long(&persistent_script_report, "memory_consumption", script->dynamic_members.memory_consumption);
607 ta = localtime(&script->dynamic_members.last_used);
608 str = asctime(ta);
609 len = strlen(str);
610 if (len > 0 && str[len - 1] == '\n') len--;
611 add_assoc_stringl(&persistent_script_report, "last_used", str, len);
612 add_assoc_long(&persistent_script_report, "last_used_timestamp", script->dynamic_members.last_used);
613 if (ZCG(accel_directives).validate_timestamps) {
614 add_assoc_long(&persistent_script_report, "timestamp", (zend_long)script->timestamp);
615 }
616 timerclear(&exec_time);
617 timerclear(&fetch_time);
618
619 add_assoc_long(&persistent_script_report, "revalidate", (zend_long)script->dynamic_members.revalidate);
620
621 zend_hash_update(Z_ARRVAL_P(return_value), cache_entry->key, &persistent_script_report);
622 }
623 }
624 accelerator_shm_read_unlock();
625
626 return 1;
627 }
628
629 /* {{{ Obtain statistics information regarding code acceleration */
630 ZEND_FUNCTION(opcache_get_status)
631 {
632 zend_long reqs;
633 zval memory_usage, statistics, scripts;
634 bool fetch_scripts = 1;
635
636 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &fetch_scripts) == FAILURE) {
637 RETURN_THROWS();
638 }
639
640 if (!validate_api_restriction()) {
641 RETURN_FALSE;
642 }
643
644 if (!accel_startup_ok) {
645 RETURN_FALSE;
646 }
647
648 array_init(return_value);
649
650 /* Trivia */
651 add_assoc_bool(return_value, "opcache_enabled", ZCG(accelerator_enabled));
652
653 if (ZCG(accel_directives).file_cache) {
654 add_assoc_string(return_value, "file_cache", ZCG(accel_directives).file_cache);
655 }
656 if (file_cache_only) {
657 add_assoc_bool(return_value, "file_cache_only", 1);
658 return;
659 }
660
661 add_assoc_bool(return_value, "cache_full", ZSMMG(memory_exhausted));
662 add_assoc_bool(return_value, "restart_pending", ZCSG(restart_pending));
663 add_assoc_bool(return_value, "restart_in_progress", ZCSG(restart_in_progress));
664
665 /* Memory usage statistics */
666 array_init(&memory_usage);
667 add_assoc_long(&memory_usage, "used_memory", ZCG(accel_directives).memory_consumption-zend_shared_alloc_get_free_memory()-ZSMMG(wasted_shared_memory));
668 add_assoc_long(&memory_usage, "free_memory", zend_shared_alloc_get_free_memory());
669 add_assoc_long(&memory_usage, "wasted_memory", ZSMMG(wasted_shared_memory));
670 add_assoc_double(&memory_usage, "current_wasted_percentage", (((double) ZSMMG(wasted_shared_memory))/ZCG(accel_directives).memory_consumption)*100.0);
671 add_assoc_zval(return_value, "memory_usage", &memory_usage);
672
673 if (ZCSG(interned_strings).start && ZCSG(interned_strings).end) {
674 zval interned_strings_usage;
675
676 array_init(&interned_strings_usage);
677 add_assoc_long(&interned_strings_usage, "buffer_size", (char*)ZCSG(interned_strings).end - (char*)(accel_shared_globals + 1));
678 add_assoc_long(&interned_strings_usage, "used_memory", (char*)ZCSG(interned_strings).top - (char*)(accel_shared_globals + 1));
679 add_assoc_long(&interned_strings_usage, "free_memory", (char*)ZCSG(interned_strings).end - (char*)ZCSG(interned_strings).top);
680 add_assoc_long(&interned_strings_usage, "number_of_strings", ZCSG(interned_strings).nNumOfElements);
681 add_assoc_zval(return_value, "interned_strings_usage", &interned_strings_usage);
682 }
683
684 /* Accelerator statistics */
685 array_init(&statistics);
686 add_assoc_long(&statistics, "num_cached_scripts", ZCSG(hash).num_direct_entries);
687 add_assoc_long(&statistics, "num_cached_keys", ZCSG(hash).num_entries);
688 add_assoc_long(&statistics, "max_cached_keys", ZCSG(hash).max_num_entries);
689 add_assoc_long(&statistics, "hits", (zend_long)ZCSG(hits));
690 add_assoc_long(&statistics, "start_time", ZCSG(start_time));
691 add_assoc_long(&statistics, "last_restart_time", ZCSG(last_restart_time));
692 add_assoc_long(&statistics, "oom_restarts", ZCSG(oom_restarts));
693 add_assoc_long(&statistics, "hash_restarts", ZCSG(hash_restarts));
694 add_assoc_long(&statistics, "manual_restarts", ZCSG(manual_restarts));
695 add_assoc_long(&statistics, "misses", ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses));
696 add_assoc_long(&statistics, "blacklist_misses", ZCSG(blacklist_misses));
697 reqs = ZCSG(hits)+ZCSG(misses);
698 add_assoc_double(&statistics, "blacklist_miss_ratio", reqs?(((double) ZCSG(blacklist_misses))/reqs)*100.0:0);
699 add_assoc_double(&statistics, "opcache_hit_rate", reqs?(((double) ZCSG(hits))/reqs)*100.0:0);
700 add_assoc_zval(return_value, "opcache_statistics", &statistics);
701
702 if (ZCSG(preload_script)) {
703 array_init(&statistics);
704
705 add_assoc_long(&statistics, "memory_consumption", ZCSG(preload_script)->dynamic_members.memory_consumption);
706
707 if (zend_hash_num_elements(&ZCSG(preload_script)->script.function_table)) {
708 zend_op_array *op_array;
709
710 array_init(&scripts);
711 ZEND_HASH_MAP_FOREACH_PTR(&ZCSG(preload_script)->script.function_table, op_array) {
712 add_next_index_str(&scripts, op_array->function_name);
713 } ZEND_HASH_FOREACH_END();
714 add_assoc_zval(&statistics, "functions", &scripts);
715 }
716
717 if (zend_hash_num_elements(&ZCSG(preload_script)->script.class_table)) {
718 zval *zv;
719 zend_string *key;
720
721 array_init(&scripts);
722 ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(&ZCSG(preload_script)->script.class_table, key, zv) {
723 if (Z_TYPE_P(zv) == IS_ALIAS_PTR) {
724 add_next_index_str(&scripts, key);
725 } else {
726 add_next_index_str(&scripts, Z_CE_P(zv)->name);
727 }
728 } ZEND_HASH_FOREACH_END();
729 add_assoc_zval(&statistics, "classes", &scripts);
730 }
731
732 if (ZCSG(saved_scripts)) {
733 zend_persistent_script **p = ZCSG(saved_scripts);
734
735 array_init(&scripts);
736 while (*p) {
737 add_next_index_str(&scripts, (*p)->script.filename);
738 p++;
739 }
740 add_assoc_zval(&statistics, "scripts", &scripts);
741 }
742 add_assoc_zval(return_value, "preload_statistics", &statistics);
743 }
744
745 if (fetch_scripts) {
746 /* accelerated scripts */
747 if (accelerator_get_scripts(&scripts)) {
748 add_assoc_zval(return_value, "scripts", &scripts);
749 }
750 }
751 #if HAVE_JIT
752 zend_jit_status(return_value);
753 #endif
754 }
755
756 static int add_blacklist_path(zend_blacklist_entry *p, zval *return_value)
757 {
758 add_next_index_stringl(return_value, p->path, p->path_length);
759 return 0;
760 }
761
762 /* {{{ Obtain configuration information */
763 ZEND_FUNCTION(opcache_get_configuration)
764 {
765 zval directives, version, blacklist;
766
767 if (zend_parse_parameters_none() == FAILURE) {
768 RETURN_THROWS();
769 }
770
771 if (!validate_api_restriction()) {
772 RETURN_FALSE;
773 }
774
775 array_init(return_value);
776
777 /* directives */
778 array_init(&directives);
779 add_assoc_bool(&directives, "opcache.enable", ZCG(enabled));
780 add_assoc_bool(&directives, "opcache.enable_cli", ZCG(accel_directives).enable_cli);
781 add_assoc_bool(&directives, "opcache.use_cwd", ZCG(accel_directives).use_cwd);
782 add_assoc_bool(&directives, "opcache.validate_timestamps", ZCG(accel_directives).validate_timestamps);
783 add_assoc_bool(&directives, "opcache.validate_permission", ZCG(accel_directives).validate_permission);
784 #ifndef ZEND_WIN32
785 add_assoc_bool(&directives, "opcache.validate_root", ZCG(accel_directives).validate_root);
786 #endif
787 add_assoc_bool(&directives, "opcache.dups_fix", ZCG(accel_directives).ignore_dups);
788 add_assoc_bool(&directives, "opcache.revalidate_path", ZCG(accel_directives).revalidate_path);
789
790 add_assoc_long(&directives, "opcache.log_verbosity_level", ZCG(accel_directives).log_verbosity_level);
791 add_assoc_long(&directives, "opcache.memory_consumption", ZCG(accel_directives).memory_consumption);
792 add_assoc_long(&directives, "opcache.interned_strings_buffer",ZCG(accel_directives).interned_strings_buffer);
793 add_assoc_long(&directives, "opcache.max_accelerated_files", ZCG(accel_directives).max_accelerated_files);
794 add_assoc_double(&directives, "opcache.max_wasted_percentage", ZCG(accel_directives).max_wasted_percentage);
795 add_assoc_long(&directives, "opcache.force_restart_timeout", ZCG(accel_directives).force_restart_timeout);
796 add_assoc_long(&directives, "opcache.revalidate_freq", ZCG(accel_directives).revalidate_freq);
797 add_assoc_string(&directives, "opcache.preferred_memory_model", STRING_NOT_NULL(ZCG(accel_directives).memory_model));
798 add_assoc_string(&directives, "opcache.blacklist_filename", STRING_NOT_NULL(ZCG(accel_directives).user_blacklist_filename));
799 add_assoc_long(&directives, "opcache.max_file_size", ZCG(accel_directives).max_file_size);
800 add_assoc_string(&directives, "opcache.error_log", STRING_NOT_NULL(ZCG(accel_directives).error_log));
801
802 add_assoc_bool(&directives, "opcache.protect_memory", ZCG(accel_directives).protect_memory);
803 add_assoc_bool(&directives, "opcache.save_comments", ZCG(accel_directives).save_comments);
804 add_assoc_bool(&directives, "opcache.record_warnings", ZCG(accel_directives).record_warnings);
805 add_assoc_bool(&directives, "opcache.enable_file_override", ZCG(accel_directives).file_override_enabled);
806 add_assoc_long(&directives, "opcache.optimization_level", ZCG(accel_directives).optimization_level);
807
808 #ifndef ZEND_WIN32
809 add_assoc_string(&directives, "opcache.lockfile_path", STRING_NOT_NULL(ZCG(accel_directives).lockfile_path));
810 #else
811 add_assoc_string(&directives, "opcache.mmap_base", STRING_NOT_NULL(ZCG(accel_directives).mmap_base));
812 #endif
813
814 add_assoc_string(&directives, "opcache.file_cache", ZCG(accel_directives).file_cache ? ZCG(accel_directives).file_cache : "");
815 add_assoc_bool(&directives, "opcache.file_cache_only", ZCG(accel_directives).file_cache_only);
816 add_assoc_bool(&directives, "opcache.file_cache_consistency_checks", ZCG(accel_directives).file_cache_consistency_checks);
817 #if ENABLE_FILE_CACHE_FALLBACK
818 add_assoc_bool(&directives, "opcache.file_cache_fallback", ZCG(accel_directives).file_cache_fallback);
819 #endif
820
821 add_assoc_long(&directives, "opcache.file_update_protection", ZCG(accel_directives).file_update_protection);
822 add_assoc_long(&directives, "opcache.opt_debug_level", ZCG(accel_directives).opt_debug_level);
823 add_assoc_string(&directives, "opcache.restrict_api", STRING_NOT_NULL(ZCG(accel_directives).restrict_api));
824 #ifdef HAVE_HUGE_CODE_PAGES
825 add_assoc_bool(&directives, "opcache.huge_code_pages", ZCG(accel_directives).huge_code_pages);
826 #endif
827 add_assoc_string(&directives, "opcache.preload", STRING_NOT_NULL(ZCG(accel_directives).preload));
828 #ifndef ZEND_WIN32
829 add_assoc_string(&directives, "opcache.preload_user", STRING_NOT_NULL(ZCG(accel_directives).preload_user));
830 #endif
831 #if ZEND_WIN32
832 add_assoc_string(&directives, "opcache.cache_id", STRING_NOT_NULL(ZCG(accel_directives).cache_id));
833 #endif
834 #ifdef HAVE_JIT
835 add_assoc_string(&directives, "opcache.jit", JIT_G(options));
836 add_assoc_long(&directives, "opcache.jit_buffer_size", JIT_G(buffer_size));
837 add_assoc_long(&directives, "opcache.jit_debug", JIT_G(debug));
838 add_assoc_long(&directives, "opcache.jit_bisect_limit", JIT_G(bisect_limit));
839 add_assoc_long(&directives, "opcache.jit_blacklist_root_trace", JIT_G(blacklist_root_trace));
840 add_assoc_long(&directives, "opcache.jit_blacklist_side_trace", JIT_G(blacklist_side_trace));
841 add_assoc_long(&directives, "opcache.jit_hot_func", JIT_G(hot_func));
842 add_assoc_long(&directives, "opcache.jit_hot_loop", JIT_G(hot_loop));
843 add_assoc_long(&directives, "opcache.jit_hot_return", JIT_G(hot_return));
844 add_assoc_long(&directives, "opcache.jit_hot_side_exit", JIT_G(hot_side_exit));
845 add_assoc_long(&directives, "opcache.jit_max_exit_counters", JIT_G(max_exit_counters));
846 add_assoc_long(&directives, "opcache.jit_max_loop_unrolls", JIT_G(max_loop_unrolls));
847 add_assoc_long(&directives, "opcache.jit_max_polymorphic_calls", JIT_G(max_polymorphic_calls));
848 add_assoc_long(&directives, "opcache.jit_max_recursive_calls", JIT_G(max_recursive_calls));
849 add_assoc_long(&directives, "opcache.jit_max_recursive_returns", JIT_G(max_recursive_returns));
850 add_assoc_long(&directives, "opcache.jit_max_root_traces", JIT_G(max_root_traces));
851 add_assoc_long(&directives, "opcache.jit_max_side_traces", JIT_G(max_side_traces));
852 add_assoc_long(&directives, "opcache.jit_prof_threshold", JIT_G(prof_threshold));
853 add_assoc_long(&directives, "opcache.jit_max_trace_length", JIT_G(max_trace_length));
854 #endif
855
856 add_assoc_zval(return_value, "directives", &directives);
857
858 /*version */
859 array_init(&version);
860 add_assoc_string(&version, "version", PHP_VERSION);
861 add_assoc_string(&version, "opcache_product_name", ACCELERATOR_PRODUCT_NAME);
862 add_assoc_zval(return_value, "version", &version);
863
864 /* blacklist */
865 array_init(&blacklist);
866 zend_accel_blacklist_apply(&accel_blacklist, add_blacklist_path, &blacklist);
867 add_assoc_zval(return_value, "blacklist", &blacklist);
868 }
869
870 /* {{{ Request that the contents of the opcode cache to be reset */
871 ZEND_FUNCTION(opcache_reset)
872 {
873 if (zend_parse_parameters_none() == FAILURE) {
874 RETURN_THROWS();
875 }
876
877 if (!validate_api_restriction()) {
878 RETURN_FALSE;
879 }
880
881 if ((!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled))
882 #if ENABLE_FILE_CACHE_FALLBACK
883 && !fallback_process
884 #endif
885 ) {
886 RETURN_FALSE;
887 }
888
889 /* exclusive lock */
890 zend_shared_alloc_lock();
891 zend_accel_schedule_restart(ACCEL_RESTART_USER);
892 zend_shared_alloc_unlock();
893 RETURN_TRUE;
894 }
895
896 /* {{{ Invalidates cached script (in necessary or forced) */
897 ZEND_FUNCTION(opcache_invalidate)
898 {
899 zend_string *script_name;
900 bool force = 0;
901
902 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|b", &script_name, &force) == FAILURE) {
903 RETURN_THROWS();
904 }
905
906 if (!validate_api_restriction()) {
907 RETURN_FALSE;
908 }
909
910 if (zend_accel_invalidate(script_name, force) == SUCCESS) {
911 RETURN_TRUE;
912 } else {
913 RETURN_FALSE;
914 }
915 }
916
917 ZEND_FUNCTION(opcache_compile_file)
918 {
919 zend_string *script_name;
920 zend_file_handle handle;
921 zend_op_array *op_array = NULL;
922 zend_execute_data *orig_execute_data = NULL;
923 uint32_t orig_compiler_options;
924
925 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &script_name) == FAILURE) {
926 RETURN_THROWS();
927 }
928
929 if (!accel_startup_ok) {
930 zend_error(E_NOTICE, ACCELERATOR_PRODUCT_NAME " has not been properly started, can't compile file");
931 RETURN_FALSE;
932 }
933
934 zend_stream_init_filename_ex(&handle, script_name);
935
936 orig_execute_data = EG(current_execute_data);
937 orig_compiler_options = CG(compiler_options);
938 CG(compiler_options) |= ZEND_COMPILE_WITHOUT_EXECUTION;
939
940 if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
941 /* During preloading, a failure in opcache_compile_file() should result in an overall
942 * preloading failure. Otherwise we may include partially compiled files in the preload
943 * state. */
944 op_array = persistent_compile_file(&handle, ZEND_INCLUDE);
945 } else {
946 zend_try {
947 op_array = persistent_compile_file(&handle, ZEND_INCLUDE);
948 } zend_catch {
949 EG(current_execute_data) = orig_execute_data;
950 zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " could not compile file %s", ZSTR_VAL(handle.filename));
951 } zend_end_try();
952 }
953
954 CG(compiler_options) = orig_compiler_options;
955
956 if(op_array != NULL) {
957 destroy_op_array(op_array);
958 efree(op_array);
959 RETVAL_TRUE;
960 } else {
961 RETVAL_FALSE;
962 }
963 zend_destroy_file_handle(&handle);
964 }
965
966 /* {{{ Return true if the script is cached in OPCache, false if it is not cached or if OPCache is not running. */
967 ZEND_FUNCTION(opcache_is_script_cached)
968 {
969 zend_string *script_name;
970
971 ZEND_PARSE_PARAMETERS_START(1, 1)
972 Z_PARAM_STR(script_name)
973 ZEND_PARSE_PARAMETERS_END();
974
975 if (!validate_api_restriction()) {
976 RETURN_FALSE;
977 }
978
979 if (!ZCG(accelerator_enabled)) {
980 RETURN_FALSE;
981 }
982
983 RETURN_BOOL(filename_is_in_cache(script_name));
984 }
985