XCache is a fast, stable PHP opcode cacher that has been proven and is now running on production servers under high load. https://xcache.lighttpd.net/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

484 lines
12 KiB

  1. #ifndef __XCACHE_H
  2. #define __XCACHE_H
  3. #define XCACHE_NAME "XCache"
  4. #ifndef XCACHE_VERSION
  5. # define XCACHE_VERSION "2.1.0"
  6. #endif
  7. #define XCACHE_AUTHOR "mOo"
  8. #define XCACHE_COPYRIGHT "Copyright (c) 2005-2012"
  9. #define XCACHE_URL "http://xcache.lighttpd.net"
  10. #define XCACHE_WIKI_URL XCACHE_URL "/wiki"
  11. #include <php.h>
  12. #include <zend_compile.h>
  13. #include <zend_API.h>
  14. #include <zend.h>
  15. #include "php_ini.h"
  16. #include "zend_hash.h"
  17. #ifdef HAVE_CONFIG_H
  18. #include <config.h>
  19. #endif
  20. #include "xc_shm.h"
  21. #include "xc_lock.h"
  22. #if !defined(ZEND_ENGINE_2_4) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4 || PHP_MAJOR_VERSION > 5)
  23. # define ZEND_ENGINE_2_4
  24. #endif
  25. #if !defined(ZEND_ENGINE_2_3) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 || defined(ZEND_ENGINE_2_4))
  26. # define ZEND_ENGINE_2_3
  27. #endif
  28. #if !defined(ZEND_ENGINE_2_2) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 2 || defined(ZEND_ENGINE_2_3))
  29. # define ZEND_ENGINE_2_2
  30. #endif
  31. #if !defined(ZEND_ENGINE_2_1) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 || defined(ZEND_ENGINE_2_2))
  32. # define ZEND_ENGINE_2_1
  33. #endif
  34. #define NOTHING
  35. /* ZendEngine code Switcher */
  36. #ifndef ZEND_ENGINE_2
  37. # define ZESW(v1, v2) v1
  38. #else
  39. # define ZESW(v1, v2) v2
  40. #endif
  41. #ifdef ZEND_ENGINE_2_4
  42. # define ZEND_24(pre24, v24) v24
  43. #else
  44. # define ZEND_24(pre24, v24) pre24
  45. #endif
  46. #ifdef do_alloca_with_limit
  47. # define my_do_alloca(size, use_heap) do_alloca_with_limit(size, use_heap)
  48. # define my_free_alloca(size, use_heap) free_alloca_with_limit(size, use_heap)
  49. #elif defined(ALLOCA_FLAG)
  50. # define my_do_alloca(size, use_heap) do_alloca(size, use_heap)
  51. # define my_free_alloca(size, use_heap) free_alloca(size, use_heap)
  52. #else
  53. # define my_do_alloca(size, use_heap) do_alloca(size)
  54. # define my_free_alloca(size, use_heap) free_alloca(size)
  55. # define ALLOCA_FLAG(x)
  56. #endif
  57. #ifndef Z_ISREF
  58. # define Z_ISREF(z) (z).is_ref
  59. #endif
  60. #ifndef Z_SET_ISREF
  61. # define Z_SET_ISREF(z) (z).is_ref = 1
  62. #endif
  63. #ifndef Z_UNSET_ISREF
  64. # define Z_UNSET_ISREF(z) (z).is_ref = 0
  65. #endif
  66. #ifndef Z_REFCOUNT
  67. # define Z_REFCOUNT(z) (z).refcount
  68. #endif
  69. #ifndef Z_SET_REFCOUNT
  70. # define Z_SET_REFCOUNT(z, rc) (z).refcount = rc
  71. #endif
  72. #ifndef IS_CONSTANT_TYPE_MASK
  73. # define IS_CONSTANT_TYPE_MASK (~IS_CONSTANT_INDEX)
  74. #endif
  75. /* {{{ dirty fix for PHP 6 */
  76. #ifdef add_assoc_long_ex
  77. static inline void my_add_assoc_long_ex(zval *arg, char *key, uint key_len, long value)
  78. {
  79. add_assoc_long_ex(arg, key, key_len, value);
  80. }
  81. # undef add_assoc_long_ex
  82. # define add_assoc_long_ex my_add_assoc_long_ex
  83. #endif
  84. #ifdef add_assoc_bool_ex
  85. static inline void my_add_assoc_bool_ex(zval *arg, char *key, uint key_len, zend_bool value)
  86. {
  87. add_assoc_bool_ex(arg, key, key_len, value);
  88. }
  89. # undef add_assoc_bool_ex
  90. # define add_assoc_bool_ex my_add_assoc_bool_ex
  91. #endif
  92. #ifdef add_assoc_null_ex
  93. static inline void my_add_assoc_null_ex(zval *arg, char *key, uint key_len)
  94. {
  95. add_assoc_null_ex(arg, key, key_len);
  96. }
  97. # undef add_assoc_null_ex
  98. # define add_assoc_null_ex my_add_assoc_null_ex
  99. #endif
  100. #ifdef ZEND_ENGINE_2_4
  101. # define Z_OP(op) (op)
  102. # define Z_OP_CONSTANT(op) (op).literal->constant
  103. # define Z_OP_TYPE(op) op##_##type
  104. # define Z_OP_TYPEOF_TYPE zend_uchar
  105. # define Z_CLASS_INFO(className) (className).info.user
  106. #else
  107. # define Z_OP(op) (op).u
  108. # define Z_OP_CONSTANT(op) (op).u.constant
  109. # define Z_OP_TYPE(op) (op).op_type
  110. # define Z_OP_TYPEOF_TYPE int
  111. typedef znode znode_op;
  112. # define Z_CLASS_INFO(className) (className)
  113. #endif
  114. /* }}} */
  115. /* unicode */
  116. #ifdef IS_UNICODE
  117. # define UNISW(text, unicode) unicode
  118. #else
  119. # define UNISW(text, unicode) text
  120. #endif
  121. #define BUCKET_KEY_SIZE(b) \
  122. (UNISW( \
  123. (b)->nKeyLength, \
  124. ((b)->key.type == IS_UNICODE) \
  125. ? UBYTES(b->nKeyLength) \
  126. : b->nKeyLength \
  127. ))
  128. #define BUCKET_KEY(b) (UNISW((b)->arKey, (b)->key.arKey))
  129. #define BUCKET_KEY_S(b) ZSTR_S(BUCKET_KEY(b))
  130. #define BUCKET_KEY_U(b) ZSTR_U(BUCKET_KEY(b))
  131. #define BUCKET_KEY_TYPE(b) (UNISW(IS_STRING, (b)->key.type))
  132. #ifdef IS_UNICODE
  133. # define BUCKET_HEAD_SIZE(b) XtOffsetOf(Bucket, key.arKey)
  134. #else
  135. # define BUCKET_HEAD_SIZE(b) XtOffsetOf(Bucket, arKey)
  136. #endif
  137. #ifdef ZEND_ENGINE_2_4
  138. # define BUCKET_SIZE(b) (sizeof(Bucket) + BUCKET_KEY_SIZE(b))
  139. #else
  140. # define BUCKET_SIZE(b) (BUCKET_HEAD_SIZE(b) + BUCKET_KEY_SIZE(b))
  141. #endif
  142. #ifndef IS_UNICODE
  143. typedef char *zstr;
  144. typedef const char *const_zstr;
  145. #ifdef ZEND_ENGINE_2_4
  146. typedef const char *const24_zstr;
  147. typedef const char *const24_str;
  148. #else
  149. typedef char *const24_zstr;
  150. typedef char *const24_str;
  151. #endif
  152. # define ZSTR_S(s) (s)
  153. # define ZSTR_U(s) (s)
  154. # define ZSTR_V(s) (s)
  155. # define ZSTR_PS(s) (s)
  156. # define ZSTR_PU(s) (s)
  157. # define ZSTR_PV(s) (s)
  158. #else
  159. typedef const zstr const_zstr;
  160. # define ZSTR_S(zs) ((zs).s)
  161. # define ZSTR_U(zs) ((zs).u)
  162. # define ZSTR_V(zs) ((zs).v)
  163. # define ZSTR_PS(pzs) ((pzs)->s)
  164. # define ZSTR_PU(pzs) ((pzs)->u)
  165. # define ZSTR_PV(pzs) ((pzs)->v)
  166. #endif
  167. #ifndef ZSTR
  168. # define ZSTR(s) (s)
  169. #endif
  170. #ifndef Z_UNIVAL
  171. # define Z_UNIVAL(zval) (zval).value.str.val
  172. # define Z_UNILEN(zval) (zval).value.str.len
  173. #endif
  174. /* {{{ u hash wrapper */
  175. #ifndef IS_UNICODE
  176. # define zend_u_hash_add(ht, type, arKey, nKeyLength, pData, nDataSize, pDest) \
  177. zend_hash_add(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength, pData, nDataSize, pDest)
  178. # define zend_u_hash_quick_add(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest) \
  179. zend_hash_quick_add(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength, h, pData, nDataSize, pDest)
  180. # define zend_u_hash_update(ht, type, arKey, nKeyLength, pData, nDataSize, pDest) \
  181. zend_hash_update(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength, pData, nDataSize, pDest)
  182. # define zend_u_hash_quick_update(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest) \
  183. zend_hash_quick_update(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength, h, pData, nDataSize, pDest)
  184. # define zend_u_hash_find(ht, type, arKey, nKeyLength, pData) \
  185. zend_hash_find(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength, pData)
  186. # define zend_u_hash_quick_find(ht, type, arKey, nKeyLength, h, pData) \
  187. zend_hash_quick_find(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength, h, pData)
  188. # define zend_u_hash_exists(ht, type, arKey, nKeyLength) \
  189. zend_hash_exists(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength)
  190. # define add_u_assoc_zval_ex(arg, type, key, key_len, value) \
  191. add_assoc_zval_ex(arg, key, key_len, value)
  192. # define zend_u_is_auto_global(type, name, name_len) \
  193. zend_is_auto_global(name, name_len)
  194. #endif
  195. /* }}} */
  196. #define ECALLOC_N(x, n) ((x) = ecalloc(n, sizeof((x)[0])))
  197. #define ECALLOC_ONE(x) ECALLOC_N(x, 1)
  198. typedef ulong xc_hash_value_t;
  199. typedef struct {
  200. size_t bits;
  201. size_t size;
  202. xc_hash_value_t mask;
  203. } xc_hash_t;
  204. /* the class entry type to be stored in class_table */
  205. typedef ZESW(zend_class_entry, zend_class_entry*) xc_cest_t;
  206. /* xc_cest_t to (zend_class_entry*) */
  207. #define CestToCePtr(st) (ZESW(\
  208. &(st), \
  209. st \
  210. ) )
  211. /* ZCEP=zend class entry ptr */
  212. #define ZCEP_REFCOUNT_PTR(pce) (ZESW( \
  213. (pce)->refcount, \
  214. &((pce)->refcount) \
  215. ))
  216. #define ZCE_REFCOUNT_PTR(ce) ZCE_REFCOUNT_PTR(&ce)
  217. typedef zend_op_array *(zend_compile_file_t)(zend_file_handle *h, int type TSRMLS_DC);
  218. typedef struct _xc_entry_t xc_entry_t;
  219. typedef struct _xc_entry_data_php_t xc_entry_data_php_t;
  220. /* {{{ xc_cache_t */
  221. typedef struct {
  222. int cacheid;
  223. xc_hash_t *hcache; /* hash to cacheid */
  224. time_t compiling;
  225. zend_ulong updates;
  226. zend_ulong hits;
  227. zend_ulong clogs;
  228. zend_ulong ooms;
  229. zend_ulong errors;
  230. xc_lock_t *lck;
  231. xc_shm_t *shm; /* which shm contains us */
  232. xc_mem_t *mem; /* which mem contains us */
  233. xc_entry_t **entries;
  234. int entries_count;
  235. xc_entry_data_php_t **phps;
  236. int phps_count;
  237. xc_entry_t *deletes;
  238. int deletes_count;
  239. xc_hash_t *hentry; /* hash settings to entry */
  240. xc_hash_t *hphp; /* hash settings to php */
  241. time_t last_gc_deletes;
  242. time_t last_gc_expires;
  243. time_t hits_by_hour_cur_time;
  244. zend_uint hits_by_hour_cur_slot;
  245. zend_ulong hits_by_hour[24];
  246. time_t hits_by_second_cur_time;
  247. zend_uint hits_by_second_cur_slot;
  248. zend_ulong hits_by_second[5];
  249. } xc_cache_t;
  250. /* }}} */
  251. /* {{{ xc_op_array_info_detail_t */
  252. typedef struct {
  253. zend_uint index;
  254. zend_uint info;
  255. } xc_op_array_info_detail_t;
  256. /* }}} */
  257. /* {{{ xc_op_array_info_t */
  258. typedef struct {
  259. #ifdef ZEND_ENGINE_2_4
  260. zend_uint literalinfo_cnt;
  261. xc_op_array_info_detail_t *literalinfos;
  262. #else
  263. zend_uint oplineinfo_cnt;
  264. xc_op_array_info_detail_t *oplineinfos;
  265. #endif
  266. } xc_op_array_info_t;
  267. /* }}} */
  268. /* {{{ xc_classinfo_t */
  269. typedef struct {
  270. #ifdef IS_UNICODE
  271. zend_uchar type;
  272. #endif
  273. const24_zstr key;
  274. zend_uint key_size;
  275. ulong h;
  276. zend_uint methodinfo_cnt;
  277. xc_op_array_info_t *methodinfos;
  278. xc_cest_t cest;
  279. #ifndef ZEND_COMPILE_DELAYED_BINDING
  280. int oplineno;
  281. #endif
  282. } xc_classinfo_t;
  283. /* }}} */
  284. #ifdef HAVE_XCACHE_CONSTANT
  285. /* {{{ xc_constinfo_t */
  286. typedef struct {
  287. #ifdef IS_UNICODE
  288. zend_uchar type;
  289. #endif
  290. const24_zstr key;
  291. zend_uint key_size;
  292. ulong h;
  293. zend_constant constant;
  294. } xc_constinfo_t;
  295. /* }}} */
  296. #endif
  297. /* {{{ xc_funcinfo_t */
  298. typedef struct {
  299. #ifdef IS_UNICODE
  300. zend_uchar type;
  301. #endif
  302. const24_zstr key;
  303. zend_uint key_size;
  304. ulong h;
  305. xc_op_array_info_t op_array_info;
  306. zend_function func;
  307. } xc_funcinfo_t;
  308. /* }}} */
  309. #ifdef ZEND_ENGINE_2_1
  310. /* {{{ xc_autoglobal_t */
  311. typedef struct {
  312. #ifdef IS_UNICODE
  313. zend_uchar type;
  314. #endif
  315. const24_zstr key;
  316. zend_uint key_len;
  317. ulong h;
  318. } xc_autoglobal_t;
  319. /* }}} */
  320. #endif
  321. typedef struct {
  322. char digest[16];
  323. } xc_md5sum_t;
  324. /* {{{ xc_compilererror_t */
  325. typedef struct {
  326. int type;
  327. uint lineno;
  328. int error_len;
  329. char *error;
  330. } xc_compilererror_t;
  331. /* }}} */
  332. /* {{{ xc_entry_data_php_t */
  333. struct _xc_entry_data_php_t {
  334. xc_entry_data_php_t *next;
  335. xc_hash_value_t hvalue;
  336. xc_md5sum_t md5; /* md5sum of the source */
  337. zend_ulong refcount; /* count of entries referencing to this data */
  338. zend_ulong hits; /* hits of this php */
  339. size_t size;
  340. xc_op_array_info_t op_array_info;
  341. zend_op_array *op_array;
  342. #ifdef HAVE_XCACHE_CONSTANT
  343. zend_uint constinfo_cnt;
  344. xc_constinfo_t *constinfos;
  345. #endif
  346. zend_uint funcinfo_cnt;
  347. xc_funcinfo_t *funcinfos;
  348. zend_uint classinfo_cnt;
  349. xc_classinfo_t *classinfos;
  350. #ifndef ZEND_COMPILE_DELAYED_BINDING
  351. zend_bool have_early_binding;
  352. #endif
  353. #ifdef ZEND_ENGINE_2_1
  354. zend_uint autoglobal_cnt;
  355. xc_autoglobal_t *autoglobals;
  356. #endif
  357. #ifdef E_STRICT
  358. zend_uint compilererror_cnt;
  359. xc_compilererror_t *compilererrors;
  360. #endif
  361. zend_bool have_references;
  362. };
  363. /* }}} */
  364. typedef zvalue_value xc_entry_name_t;
  365. /* {{{ xc_entry_t */
  366. struct _xc_entry_t {
  367. xc_entry_t *next;
  368. size_t size;
  369. time_t ctime; /* creation ctime of this entry */
  370. time_t atime; /* access atime of this entry */
  371. time_t dtime; /* deletion time of this entry */
  372. zend_ulong hits;
  373. zend_ulong ttl;
  374. xc_entry_name_t name;
  375. };
  376. typedef struct {
  377. xc_entry_t entry;
  378. xc_entry_data_php_t *php;
  379. zend_ulong refcount; /* count of php instances holding this entry */
  380. time_t file_mtime;
  381. size_t file_size;
  382. int file_device;
  383. int file_inode;
  384. int filepath_len;
  385. ZEND_24(NOTHING, const) char *filepath;
  386. int dirpath_len;
  387. char *dirpath;
  388. #ifdef IS_UNICODE
  389. int ufilepath_len;
  390. UChar *ufilepath;
  391. int udirpath_len;
  392. UChar *udirpath;
  393. #endif
  394. } xc_entry_php_t;
  395. typedef struct {
  396. xc_entry_t entry;
  397. #ifdef IS_UNICODE
  398. zend_uchar name_type;
  399. #endif
  400. zval *value;
  401. zend_bool have_references;
  402. } xc_entry_var_t;
  403. /* }}} */
  404. typedef struct xc_entry_hash_t { /* {{{ */
  405. xc_hash_value_t cacheid;
  406. xc_hash_value_t entryslotid;
  407. } xc_entry_hash_t;
  408. /* }}} */
  409. extern zend_module_entry xcache_module_entry;
  410. #define phpext_xcache_ptr &xcache_module_entry
  411. int xc_is_rw(const void *p);
  412. int xc_is_ro(const void *p);
  413. int xc_is_shm(const void *p);
  414. /* {{{ xc_gc_op_array_t */
  415. typedef struct {
  416. #ifdef ZEND_ENGINE_2
  417. zend_uint num_args;
  418. zend_arg_info *arg_info;
  419. #endif
  420. zend_op *opcodes;
  421. } xc_gc_op_array_t;
  422. /* }}} */
  423. void xc_gc_add_op_array(xc_gc_op_array_t *gc_op_array TSRMLS_DC);
  424. void xc_fix_op_array_info(const xc_entry_php_t *xce, const xc_entry_data_php_t *php, zend_op_array *op_array, int shallow_copy, const xc_op_array_info_t *op_array_info TSRMLS_DC);
  425. #endif /* __XCACHE_H */