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