zend_accelerator_module.c 40 KB

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