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