xref: /PHP-7.0/ext/opcache/ZendAccelerator.h (revision 60912e66)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend OPcache                                                         |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2017 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    | http://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@zend.com>                                |
16    |          Zeev Suraski <zeev@zend.com>                                |
17    |          Stanislav Malyshev <stas@zend.com>                          |
18    |          Dmitry Stogov <dmitry@zend.com>                             |
19    +----------------------------------------------------------------------+
20 */
21 
22 #ifndef ZEND_ACCELERATOR_H
23 #define ZEND_ACCELERATOR_H
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #define ACCELERATOR_PRODUCT_NAME	"Zend OPcache"
30 /* 2 - added Profiler support, on 20010712 */
31 /* 3 - added support for Optimizer's encoded-only-files mode */
32 /* 4 - works with the new Optimizer, that supports the file format with licenses */
33 /* 5 - API 4 didn't really work with the license-enabled file format.  v5 does. */
34 /* 6 - Monitor was removed from ZendPlatform.so, to a module of its own */
35 /* 7 - Optimizer was embedded into Accelerator */
36 /* 8 - Standalone Open Source Zend OPcache */
37 #define ACCELERATOR_API_NO 8
38 
39 #if ZEND_WIN32
40 # include "zend_config.w32.h"
41 #else
42 #include "zend_config.h"
43 # include <sys/time.h>
44 # include <sys/resource.h>
45 #endif
46 
47 #if HAVE_UNISTD_H
48 # include "unistd.h"
49 #endif
50 
51 #include "zend_extensions.h"
52 #include "zend_compile.h"
53 
54 #include "Optimizer/zend_optimizer.h"
55 #include "zend_accelerator_hash.h"
56 #include "zend_accelerator_debug.h"
57 
58 #ifndef PHPAPI
59 # ifdef ZEND_WIN32
60 #  define PHPAPI __declspec(dllimport)
61 # else
62 #  define PHPAPI
63 # endif
64 #endif
65 
66 #ifndef ZEND_EXT_API
67 # if WIN32|WINNT
68 #  define ZEND_EXT_API __declspec(dllexport)
69 # elif defined(__GNUC__) && __GNUC__ >= 4
70 #  define ZEND_EXT_API __attribute__ ((visibility("default")))
71 # else
72 #  define ZEND_EXT_API
73 # endif
74 #endif
75 
76 #ifdef ZEND_WIN32
77 # ifndef MAXPATHLEN
78 #  define MAXPATHLEN     _MAX_PATH
79 # endif
80 # include <direct.h>
81 #else
82 # ifndef MAXPATHLEN
83 #  define MAXPATHLEN     4096
84 # endif
85 # include <sys/param.h>
86 #endif
87 
88 #define PHP_5_0_X_API_NO		220040412
89 #define PHP_5_1_X_API_NO		220051025
90 #define PHP_5_2_X_API_NO		220060519
91 #define PHP_5_3_X_API_NO		220090626
92 #define PHP_5_4_X_API_NO		220100525
93 #define PHP_5_5_X_API_NO		220121212
94 #define PHP_5_6_X_API_NO		220131226
95 
96 /*** file locking ***/
97 #ifndef ZEND_WIN32
98 extern int lock_file;
99 
100 # if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || (defined(__APPLE__) && defined(__MACH__)/* Darwin */) || defined(__OpenBSD__) || defined(__NetBSD__)
101 #  define FLOCK_STRUCTURE(name, type, whence, start, len) \
102 		struct flock name = {start, len, -1, type, whence}
103 # elif defined(__svr4__)
104 #  define FLOCK_STRUCTURE(name, type, whence, start, len) \
105 		struct flock name = {type, whence, start, len}
106 # elif defined(__linux__) || defined(__hpux) || defined(__GNU__)
107 #  define FLOCK_STRUCTURE(name, type, whence, start, len) \
108 		struct flock name = {type, whence, start, len, 0}
109 # elif defined(_AIX)
110 #  if defined(_LARGE_FILES) || defined(__64BIT__)
111 #   define FLOCK_STRUCTURE(name, type, whence, start, len) \
112 		struct flock name = {type, whence, 0, 0, 0, start, len }
113 #  else
114 #   define FLOCK_STRUCTURE(name, type, whence, start, len) \
115 		struct flock name = {type, whence, start, len}
116 #  endif
117 # elif defined(HAVE_FLOCK_BSD)
118 #  define FLOCK_STRUCTURE(name, type, whence, start, len) \
119 		struct flock name = {start, len, -1, type, whence}
120 # elif defined(HAVE_FLOCK_LINUX)
121 #  define FLOCK_STRUCTURE(name, type, whence, start, len) \
122 		struct flock name = {type, whence, start, len}
123 # else
124 #  error "Don't know how to define struct flock"
125 # endif
126 #endif
127 
128 #define PZ_REFCOUNT_P(pz)				(pz)->refcount__gc
129 #define PZ_SET_REFCOUNT_P(pz, v)		(pz)->refcount__gc = (v)
130 #define PZ_ADDREF_P(pz)					++((pz)->refcount__gc)
131 #define PZ_DELREF_P(pz)					--((pz)->refcount__gc)
132 #define PZ_ISREF_P(pz)					(pz)->is_ref__gc
133 #define PZ_SET_ISREF_P(pz)				Z_SET_ISREF_TO_P(pz, 1)
134 #define PZ_UNSET_ISREF_P(pz)			Z_SET_ISREF_TO_P(pz, 0)
135 #define PZ_SET_ISREF_TO_P(pz, isref)	(pz)->is_ref__gc = (isref)
136 
137 #define DO_ALLOCA(x)	do_alloca(x, use_heap)
138 #define FREE_ALLOCA(x)	free_alloca(x, use_heap)
139 
140 #if defined(HAVE_OPCACHE_FILE_CACHE) && defined(ZEND_WIN32)
141 # define ENABLE_FILE_CACHE_FALLBACK 1
142 #endif
143 
144 #if ZEND_WIN32
145 typedef unsigned __int64 accel_time_t;
146 #else
147 typedef time_t accel_time_t;
148 #endif
149 
150 typedef enum _zend_accel_restart_reason {
151 	ACCEL_RESTART_OOM,    /* restart because of out of memory */
152 	ACCEL_RESTART_HASH,   /* restart because of hash overflow */
153 	ACCEL_RESTART_USER    /* restart scheduled by opcache_reset() */
154 } zend_accel_restart_reason;
155 
156 typedef struct _zend_persistent_script {
157 	zend_string   *full_path;              /* full real path with resolved symlinks */
158 	zend_op_array  main_op_array;
159 	HashTable      function_table;
160 	HashTable      class_table;
161 	zend_long           compiler_halt_offset;   /* position of __HALT_COMPILER or -1 */
162 	int            ping_auto_globals_mask; /* which autoglobals are used by the script */
163 	accel_time_t   timestamp;              /* the script modification time */
164 	zend_bool      corrupted;
165 	zend_bool      is_phar;
166 
167 	void          *mem;                    /* shared memory area used by script structures */
168 	size_t         size;                   /* size of used shared memory */
169 	void          *arena_mem;              /* part that should be copied into process */
170 	size_t         arena_size;
171 
172 	/* All entries that shouldn't be counted in the ADLER32
173 	 * checksum must be declared in this struct
174 	 */
175 	struct zend_persistent_script_dynamic_members {
176 		time_t       last_used;
177 #ifdef ZEND_WIN32
178 		LONGLONG   hits;
179 #else
180 		zend_ulong        hits;
181 #endif
182 		unsigned int memory_consumption;
183 		unsigned int checksum;
184 		time_t       revalidate;
185 	} dynamic_members;
186 } zend_persistent_script;
187 
188 typedef struct _zend_accel_directives {
189 	zend_long           memory_consumption;
190 	zend_long           max_accelerated_files;
191 	double         max_wasted_percentage;
192 	char          *user_blacklist_filename;
193 	zend_long           consistency_checks;
194 	zend_long           force_restart_timeout;
195 	zend_bool      use_cwd;
196 	zend_bool      ignore_dups;
197 	zend_bool      validate_timestamps;
198 	zend_bool      revalidate_path;
199 	zend_bool      save_comments;
200 	zend_bool      fast_shutdown;
201 	zend_bool      protect_memory;
202 	zend_bool      file_override_enabled;
203 	zend_bool      inherited_hack;
204 	zend_bool      enable_cli;
205 	zend_bool      validate_permission;
206 #ifndef ZEND_WIN32
207 	zend_bool      validate_root;
208 #endif
209 	zend_ulong     revalidate_freq;
210 	zend_ulong     file_update_protection;
211 	char          *error_log;
212 #ifdef ZEND_WIN32
213 	char          *mmap_base;
214 #endif
215 	char          *memory_model;
216 	zend_long           log_verbosity_level;
217 
218 	zend_long           optimization_level;
219 	zend_long           max_file_size;
220 	zend_long           interned_strings_buffer;
221 	char          *restrict_api;
222 #ifndef ZEND_WIN32
223 	char          *lockfile_path;
224 #endif
225 #ifdef HAVE_OPCACHE_FILE_CACHE
226 	char          *file_cache;
227 	zend_bool      file_cache_only;
228 	zend_bool      file_cache_consistency_checks;
229 #endif
230 #if ENABLE_FILE_CACHE_FALLBACK
231 	zend_bool      file_cache_fallback;
232 #endif
233 #ifdef HAVE_HUGE_CODE_PAGES
234 	zend_bool      huge_code_pages;
235 #endif
236 } zend_accel_directives;
237 
238 typedef struct _zend_accel_globals {
239     /* copy of CG(function_table) used for compilation scripts into cache */
240     /* initially it contains only internal functions */
241 	HashTable               function_table;
242 	int                     internal_functions_count;
243 	int                     counted;   /* the process uses shared memory */
244 	zend_bool               enabled;
245 	zend_bool               locked;    /* thread obtained exclusive lock */
246 	HashTable               bind_hash; /* prototype and zval lookup table */
247 	zend_accel_directives   accel_directives;
248 	zend_string            *cwd;                  /* current working directory or NULL */
249 	zend_string            *include_path;         /* current value of "include_path" directive */
250 	char                    include_path_key[32]; /* key of current "include_path" */
251 	char                    cwd_key[32];          /* key of current working directory */
252 	int                     include_path_key_len;
253 	int                     include_path_check;
254 	int                     cwd_key_len;
255 	int                     cwd_check;
256 	int                     auto_globals_mask;
257 	time_t                  request_time;
258 	time_t                  last_restart_time; /* used to synchronize SHM and in-process caches */
259 	char                    system_id[32];
260 	HashTable               xlat_table;
261 #ifndef ZEND_WIN32
262 	zend_ulong              root_hash;
263 #endif
264 	/* preallocated shared-memory block to save current script */
265 	void                   *mem;
266 	void                   *arena_mem;
267 	zend_persistent_script *current_persistent_script;
268 	/* cache to save hash lookup on the same INCLUDE opcode */
269 	const zend_op          *cache_opline;
270 	zend_persistent_script *cache_persistent_script;
271 	/* preallocated buffer for keys */
272 	int                     key_len;
273 	char                    key[MAXPATHLEN * 8];
274 } zend_accel_globals;
275 
276 typedef struct _zend_accel_shared_globals {
277 	/* Cache Data Structures */
278 	zend_ulong   hits;
279 	zend_ulong   misses;
280 	zend_ulong   blacklist_misses;
281 	zend_ulong   oom_restarts;     /* number of restarts because of out of memory */
282 	zend_ulong   hash_restarts;    /* number of restarts because of hash overflow */
283 	zend_ulong   manual_restarts;  /* number of restarts scheduled by opcache_reset() */
284 	zend_accel_hash hash;             /* hash table for cached scripts */
285 
286 	/* Directives & Maintenance */
287 	time_t          start_time;
288 	time_t          last_restart_time;
289 	time_t          force_restart_time;
290 	zend_bool       accelerator_enabled;
291 	zend_bool       restart_pending;
292 	zend_accel_restart_reason restart_reason;
293 	zend_bool       cache_status_before_restart;
294 #ifdef ZEND_WIN32
295 	LONGLONG   mem_usage;
296 	LONGLONG   restart_in;
297 #endif
298 	zend_bool       restart_in_progress;
299 	/* Interned Strings Support */
300 	char           *interned_strings_start;
301 	char           *interned_strings_top;
302 	char           *interned_strings_end;
303 	char           *interned_strings_saved_top;
304 	HashTable       interned_strings;
305 } zend_accel_shared_globals;
306 
307 extern zend_bool accel_startup_ok;
308 #if ENABLE_FILE_CACHE_FALLBACK
309 extern zend_bool fallback_process;
310 #endif
311 
312 extern zend_accel_shared_globals *accel_shared_globals;
313 #define ZCSG(element)   (accel_shared_globals->element)
314 
315 #ifdef ZTS
316 # define ZCG(v)	ZEND_TSRMG(accel_globals_id, zend_accel_globals *, v)
317 extern int accel_globals_id;
318 # ifdef COMPILE_DL_OPCACHE
319 ZEND_TSRMLS_CACHE_EXTERN()
320 # endif
321 #else
322 # define ZCG(v) (accel_globals.v)
323 extern zend_accel_globals accel_globals;
324 #endif
325 
326 extern char *zps_api_failure_reason;
327 
328 void accel_shutdown(void);
329 int  accel_post_deactivate(void);
330 void zend_accel_schedule_restart(zend_accel_restart_reason reason);
331 void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason);
332 accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size);
333 int  validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle);
334 int  validate_timestamp_and_record_ex(zend_persistent_script *persistent_script, zend_file_handle *file_handle);
335 int  zend_accel_invalidate(const char *filename, int filename_len, zend_bool force);
336 int  zend_accel_script_optimize(zend_persistent_script *persistent_script);
337 int  accelerator_shm_read_lock(void);
338 void accelerator_shm_read_unlock(void);
339 
340 char *accel_make_persistent_key(const char *path, int path_length, int *key_len);
341 zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type);
342 
343 #if !defined(ZEND_DECLARE_INHERITED_CLASS_DELAYED)
344 # define ZEND_DECLARE_INHERITED_CLASS_DELAYED 145
345 #endif
346 
347 #define ZEND_DECLARE_INHERITED_CLASS_DELAYED_FLAG 0x80
348 
349 #define IS_ACCEL_INTERNED(str) \
350 	((char*)(str) >= ZCSG(interned_strings_start) && (char*)(str) < ZCSG(interned_strings_end))
351 
352 zend_string *accel_new_interned_string(zend_string *str);
353 
354 # define ZEND_RESULT_TYPE(opline)	(opline)->result_type
355 # define ZEND_RESULT(opline)		(opline)->result
356 # define ZEND_OP1_TYPE(opline)		(opline)->op1_type
357 # define ZEND_OP1(opline)			(opline)->op1
358 # define ZEND_OP1_CONST(opline)		(*(opline)->op1.zv)
359 # define ZEND_OP1_LITERAL(opline)	(op_array)->literals[(opline)->op1.constant]
360 # define ZEND_OP2_TYPE(opline)		(opline)->op2_type
361 # define ZEND_OP2(opline)			(opline)->op2
362 # define ZEND_OP2_CONST(opline)		(*(opline)->op2.zv)
363 # define ZEND_OP2_LITERAL(opline)	(op_array)->literals[(opline)->op2.constant]
364 # define ZEND_DONE_PASS_TWO(op_array)	(((op_array)->fn_flags & ZEND_ACC_DONE_PASS_TWO) != 0)
365 # define ZEND_CE_FILENAME(ce)			(ce)->info.user.filename
366 # define ZEND_CE_DOC_COMMENT(ce)        (ce)->info.user.doc_comment
367 # define ZEND_CE_DOC_COMMENT_LEN(ce)	(ce)->info.user.doc_comment_len
368 
369 #endif /* ZEND_ACCELERATOR_H */
370