60#if __has_feature(memory_sanitizer)
61# include <sanitizer/msan_interface.h>
65#define zend_file_cache_unlink unlink
66#define zend_file_cache_open open
68#define zend_file_cache_unlink php_win32_ioutil_unlink
69#define zend_file_cache_open php_win32_ioutil_open
76static int zend_file_cache_flock(
int fd,
int op)
80 if (LockFileEx((HANDLE)_get_osfhandle(
fd),
81 LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &
offset) ==
TRUE) {
85 if (LockFileEx((HANDLE)_get_osfhandle(
fd),
90 if (UnlockFileEx((HANDLE)_get_osfhandle(
fd),
97#elif defined(HAVE_FLOCK)
98# define zend_file_cache_flock flock
103static int zend_file_cache_flock(
int fd,
int type)
115#define IS_SERIALIZED_INTERNED(ptr) \
116 ((size_t)(ptr) & Z_UL(1))
121#define IS_SERIALIZED(ptr) \
122 ((char*)(ptr) <= (char*)script->size)
123#define IS_UNSERIALIZED(ptr) \
124 (((char*)(ptr) >= (char*)script->mem && (char*)(ptr) <= (char*)script->mem + script->size) || \
125 IS_ACCEL_INTERNED(ptr))
126#define SERIALIZE_PTR(ptr) do { \
128 ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \
129 (ptr) = (void*)((char*)(ptr) - (char*)script->mem); \
132#define UNSERIALIZE_PTR(ptr) do { \
134 ZEND_ASSERT(IS_SERIALIZED(ptr)); \
135 (ptr) = (void*)((char*)buf + (size_t)(ptr)); \
138#define SERIALIZE_STR(ptr) do { \
140 if (IS_ACCEL_INTERNED(ptr)) { \
141 (ptr) = zend_file_cache_serialize_interned((zend_string*)(ptr), info); \
143 ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \
145 if (EXPECTED(script->corrupted)) { \
146 GC_ADD_FLAGS(ptr, IS_STR_INTERNED); \
147 GC_DEL_FLAGS(ptr, IS_STR_PERMANENT); \
149 (ptr) = (void*)((char*)(ptr) - (char*)script->mem); \
153#define UNSERIALIZE_STR(ptr) do { \
155 if (IS_SERIALIZED_INTERNED(ptr)) { \
156 (ptr) = (void*)zend_file_cache_unserialize_interned((zend_string*)(ptr), !script->corrupted); \
158 ZEND_ASSERT(IS_SERIALIZED(ptr)); \
159 (ptr) = (void*)((char*)buf + (size_t)(ptr)); \
161 if (EXPECTED(!script->corrupted)) { \
162 GC_ADD_FLAGS(ptr, IS_STR_INTERNED | IS_STR_PERMANENT); \
164 GC_ADD_FLAGS(ptr, IS_STR_INTERNED); \
165 GC_DEL_FLAGS(ptr, IS_STR_PERMANENT); \
171#define SERIALIZE_ATTRIBUTES(attributes) do { \
172 if ((attributes) && !IS_SERIALIZED(attributes)) { \
174 SERIALIZE_PTR(attributes); \
176 UNSERIALIZE_PTR(ht); \
177 zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_attribute); \
181#define UNSERIALIZE_ATTRIBUTES(attributes) do { \
182 if ((attributes) && !IS_UNSERIALIZED(attributes)) { \
184 UNSERIALIZE_PTR(attributes); \
186 zend_file_cache_unserialize_hash(ht, script, buf, zend_file_cache_unserialize_attribute, NULL); \
190#define HOOKED_ITERATOR_PLACEHOLDER ((void*)1)
192static const uint32_t uninitialized_bucket[-
HT_MIN_MASK] =
205static int zend_file_cache_mkdir(
char *filename,
size_t start)
207 char *
s = filename +
start;
214 if (
mkdir(filename, S_IRWXU) < 0 &&
errno != EEXIST) {
216 if (php_win32_ioutil_mkdir(filename, 0700) < 0 &&
errno != EEXIST) {
237static void zend_file_cache_serialize_zval(
zval *
zv,
241static void zend_file_cache_unserialize_zval(
zval *
zv,
245static void *zend_file_cache_serialize_interned(
zend_string *str,
264 s = zend_string_realloc(
279static void *zend_file_cache_unserialize_interned(
zend_string *str,
bool in_shm)
303static void zend_file_cache_serialize_hash(
HashTable *
ht,
346static void zend_file_cache_serialize_ast(
zend_ast *ast,
356 }
else if (zend_ast_is_list(ast)) {
358 for (i = 0; i < list->
children; i++) {
361 tmp = list->
child[i];
363 zend_file_cache_serialize_ast(tmp, script, info,
buf);
367 uint32_t children = zend_ast_get_num_children(ast);
368 for (i = 0; i < children; i++) {
373 zend_file_cache_serialize_ast(tmp, script, info,
buf);
379static void zend_file_cache_serialize_zval(
zval *
zv,
397 zend_file_cache_serialize_hash(
ht, script, info,
buf, zend_file_cache_serialize_zval);
407 zend_file_cache_serialize_ast(
GC_AST(ast), script, info,
buf);
420static void zend_file_cache_serialize_attribute(
zval *
zv,
435 for (i = 0; i <
attr->argc; i++) {
437 zend_file_cache_serialize_zval(&
attr->args[i].value, script, info,
buf);
441static void zend_file_cache_serialize_type(
452 zend_file_cache_serialize_type(list_type, script, info,
buf);
461static void zend_file_cache_serialize_op_array(
zend_op_array *op_array,
475 if (op_array->
scope) {
477 op_array->
refcount = (uint32_t*)(intptr_t)-1;
503 zend_file_cache_serialize_hash(
ht, script, info,
buf, zend_file_cache_serialize_zval);
514 zend_file_cache_serialize_zval(
p, script, info,
buf);
522#if !ZEND_USE_ABS_CONST_ADDR
531 while (opline <
end) {
532#if ZEND_USE_ABS_CONST_ADDR
547#if ZEND_USE_ABS_JMP_ADDR
601 zend_file_cache_serialize_type(&
p->type, script, info,
buf);
606 if (op_array->
vars) {
631 zend_file_cache_serialize_op_array(def, script, info,
buf);
647static void zend_file_cache_serialize_func(
zval *
zv,
657 zend_file_cache_serialize_op_array(&
func->op_array, script, info,
buf);
660static void zend_file_cache_serialize_prop_info(
zval *
zv,
690 zend_file_cache_serialize_op_array(&hook->
op_array, script, info,
buf);
694 zend_file_cache_serialize_type(&prop->
type, script, info,
buf);
699static void zend_file_cache_serialize_class_constant(
zval *
zv,
715 zend_file_cache_serialize_zval(&c->
value, script, info,
buf);
721 zend_file_cache_serialize_type(&c->
type, script, info,
buf);
726static void zend_file_cache_serialize_class(
zval *
zv,
745 zend_file_cache_serialize_hash(&ce->
function_table, script, info,
buf, zend_file_cache_serialize_func);
754 zend_file_cache_serialize_zval(
p, script, info,
buf);
767 zend_file_cache_serialize_zval(
p, script, info,
buf);
771 zend_file_cache_serialize_hash(&ce->
constants_table, script, info,
buf, zend_file_cache_serialize_class_constant);
775 zend_file_cache_serialize_hash(&ce->
properties_info, script, info,
buf, zend_file_cache_serialize_prop_info);
916static void zend_file_cache_serialize_warnings(
936static void zend_file_cache_serialize_early_bindings(
969 zend_file_cache_serialize_hash(&new_script->
script.
class_table, script, info,
buf, zend_file_cache_serialize_class);
970 zend_file_cache_serialize_hash(&new_script->
script.
function_table, script, info,
buf, zend_file_cache_serialize_func);
972 zend_file_cache_serialize_warnings(new_script, info,
buf);
973 zend_file_cache_serialize_early_bindings(new_script, info,
buf);
978static char *zend_file_cache_get_bin_file_path(
zend_string *script_path)
986 memcpy(filename,
ZCG(accel_directives).file_cache,
len);
996 memcpy(filename,
ZCG(accel_directives).file_cache,
len);
997 filename[
len] =
'\\';
998 memcpy(filename + 1 +
len, accel_uname_id, 32);
1000 filename[
len] =
'\\';
1006 *(filename +
len + 33) =
'\\';
1009 *(filename +
len + 38) =
'\\';
1010 *(filename +
len + 39) =
ZSTR_VAL(script_path)[7];
1017 }
else if (
ZSTR_LEN(script_path) >= 2 &&
':' ==
ZSTR_VAL(script_path)[1]) {
1019 *(filename +
len + 33) =
'\\';
1020 *(filename +
len + 34) =
ZSTR_VAL(script_path)[0];
1041 const ssize_t total_size = (ssize_t)(
sizeof(*info) + script->
size + info->
str_size);
1043#ifdef HAVE_SYS_UIO_H
1044 const struct iovec vec[] = {
1045 { .iov_base = (
void *)info, .iov_len =
sizeof(*info) },
1046 { .iov_base = (
void *)
buf, .iov_len = script->
size },
1050 written = writev(
fd, vec,
sizeof(vec) /
sizeof(vec[0]));
1051 if (
EXPECTED(written == total_size)) {
1067 written = write(
fd, info,
sizeof(*info));
1103 filename = zend_file_cache_get_bin_file_path(script->
script.
filename);
1105 if (zend_file_cache_mkdir(filename,
strlen(
ZCG(accel_directives).file_cache)) !=
SUCCESS) {
1113 if (
errno != EEXIST) {
1120 if (zend_file_cache_flock(
fd,
LOCK_EX) != 0) {
1126#if defined(__AVX__) || defined(__SSE2__)
1129 buf = (
void*)(((uintptr_t)mem + 63L) & ~63L);
1140 zend_file_cache_serialize(script, &info,
buf);
1148#if __has_feature(memory_sanitizer)
1152 __msan_unpoison(&info,
sizeof(info));
1153 __msan_unpoison(
buf, script->
size);
1159 if (!zend_file_cache_script_write(
fd, script, &info,
buf,
s)) {
1171 if (zend_file_cache_flock(
fd,
LOCK_UN) != 0) {
1180static void zend_file_cache_unserialize_hash(
HashTable *
ht,
1186 ht->pDestructor = dtor;
1225static void zend_file_cache_unserialize_ast(
zend_ast *ast,
1233 }
else if (zend_ast_is_list(ast)) {
1235 for (i = 0; i < list->
children; i++) {
1238 zend_file_cache_unserialize_ast(list->
child[i], script,
buf);
1242 uint32_t children = zend_ast_get_num_children(ast);
1243 for (i = 0; i < children; i++) {
1246 zend_file_cache_unserialize_ast(ast->
child[i], script,
buf);
1252static void zend_file_cache_unserialize_zval(
zval *
zv,
1270 zend_file_cache_unserialize_hash(
ht,
1301 for (i = 0; i <
attr->argc; i++) {
1303 zend_file_cache_unserialize_zval(&
attr->args[i].value, script,
buf);
1307static void zend_file_cache_unserialize_type(
1317 zend_file_cache_unserialize_type(list_type,
scope, script,
buf);
1331static void zend_file_cache_unserialize_op_array(
zend_op_array *op_array,
1382 zend_file_cache_unserialize_hash(
ht,
1393 zend_file_cache_unserialize_zval(
p, script,
buf);
1403 end = opline + op_array->
last;
1404 while (opline <
end) {
1405#if ZEND_USE_ABS_CONST_ADDR
1420#if ZEND_USE_ABS_JMP_ADDR
1421 switch (opline->
opcode) {
1479 if (op_array->
vars) {
1512static void zend_file_cache_unserialize_func(
zval *
zv,
1520 zend_file_cache_unserialize_op_array(&
func->op_array, script,
buf);
1523static void zend_file_cache_unserialize_prop_info(
zval *
zv,
1545 if (prop->
hooks[i]) {
1547 zend_file_cache_unserialize_op_array(&prop->
hooks[i]->
op_array, script,
buf);
1551 zend_file_cache_unserialize_type(&prop->
type, prop->
ce, script,
buf);
1556static void zend_file_cache_unserialize_class_constant(
zval *
zv,
1570 zend_file_cache_unserialize_zval(&c->
value, script,
buf);
1576 zend_file_cache_unserialize_type(&c->
type, c->
ce, script,
buf);
1581static void zend_file_cache_unserialize_class(
zval *
zv,
1614 zend_file_cache_unserialize_zval(
p, script,
buf);
1624 zend_file_cache_unserialize_zval(
p, script,
buf);
1629 script,
buf, zend_file_cache_unserialize_class_constant,
NULL);
1634 script,
buf, zend_file_cache_unserialize_prop_info,
NULL);
1808 zend_file_cache_unserialize_warnings(script,
buf);
1809 zend_file_cache_unserialize_early_bindings(script,
buf);
1820 void *mem, *checkpoint, *
buf;
1821 bool cache_it =
true;
1822 unsigned int actual_checksum;
1828 filename = zend_file_cache_get_bin_file_path(full_path);
1836 if (zend_file_cache_flock(
fd,
LOCK_SH) != 0) {
1842 if (read(
fd, &info,
sizeof(info)) !=
sizeof(info)) {
1852 if (memcmp(info.
magic,
"OPCACHE", 8) != 0) {
1870 if (
ZCG(accel_directives).validate_timestamps &&
1872 if (zend_file_cache_flock(
fd,
LOCK_UN) != 0) {
1881 checkpoint = zend_arena_checkpoint(
CG(
arena));
1882#if defined(__AVX__) || defined(__SSE2__)
1885 mem = (
void*)(((uintptr_t)mem + 63L) & ~63L);
1895 zend_arena_release(&
CG(
arena), checkpoint);
1899 if (zend_file_cache_flock(
fd,
LOCK_UN) != 0) {
1905 if (
ZCG(accel_directives).file_cache_consistency_checks &&
1909 zend_arena_release(&
CG(
arena), checkpoint);
1915 !
ZCSG(restart_in_progress) &&
1916 !
ZCSG(restart_pending) &&
1917 !
ZSMMG(memory_exhausted) &&
1930 zend_arena_release(&
CG(
arena), checkpoint);
1936 if (zend_accel_hash_is_full(&
ZCSG(
hash))) {
1938 ZSMMG(memory_exhausted) = 1;
1941 goto use_process_mem;
1949 goto use_process_mem;
1965 zend_file_cache_unserialize(script,
buf);
1972 goto use_process_mem;
1974 zend_arena_release(&
CG(
arena), checkpoint);
1983 ZCSG(map_ptr_last) =
CG(map_ptr_last);
1991 zend_arena_release(&
CG(
arena), checkpoint);
2002 filename = zend_file_cache_get_bin_file_path(full_path);
accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size)
void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason)
zend_result accelerator_shm_read_lock(void)
zend_string *ZEND_FASTCALL accel_new_interned_string(zend_string *str)
struct _zend_persistent_script zend_persistent_script
struct _zend_early_binding zend_early_binding
mkdir(string $directory, int $permissions=0777, bool $recursive=false, $context=null)
zend_ffi_ctype_name_buf buf
hash(string $algo, string $data, bool $binary=false, array $options=[])
unsigned const char * end
zend_function * zf_offsetget
zend_function * zf_offsetunset
zend_function * zf_offsetset
zend_function * zf_offsetexists
zend_string * doc_comment
HashTable constants_table
zend_function * __debugInfo
zend_function * __tostring
zend_class_iterator_funcs * iterator_funcs_ptr
zval * default_static_members_table
struct _zend_class_entry::@126215362204241324314155352336150042254204116267::@166057154351252324007362117353350250255142166322 user
HashTable properties_info
zend_trait_precedence ** trait_precedences
zend_object_iterator *(* get_iterator)(zend_class_entry *ce, zval *object, int by_ref)
zend_class_name * trait_names
zend_class_name * interface_names
zend_function * __unserialize
union _zend_class_entry::@126215362204241324314155352336150042254204116267 info
zend_class_arrayaccess_funcs * arrayaccess_funcs_ptr
zend_string * parent_name
int default_properties_count
zend_function * __serialize
zend_trait_alias ** trait_aliases
int default_static_members_count
zend_function * constructor
zend_inheritance_cache_entry * inheritance_cache
struct _zend_property_info ** properties_info_table
zend_class_entry * parent
zend_string * doc_comment
zval * default_properties_table
const zend_object_handlers * default_object_handlers
zend_function * __callstatic
zend_function * destructor
zend_function * zf_new_iterator
zend_function * zf_current
zend_function * zf_rewind
zend_string * lc_parent_name
zend_string * opened_path
zend_function * prototype
HashTable * static_variables
zend_op_array ** dynamic_func_defs
const zend_property_info * prop_info
zend_string * doc_comment
zend_try_catch_element * try_catch_array
zend_live_range * live_range
zend_string * function_name
uint32_t num_dynamic_func_defs
uint32_t num_early_bindings
zend_early_binding * early_bindings
struct _zend_persistent_script::zend_persistent_script_dynamic_members dynamic_members
zend_error_info ** warnings
const zend_property_info * prototype
zend_string * doc_comment
zend_op_array main_op_array
zend_trait_method_reference trait_method
zend_string * method_name
zend_trait_method_reference trait_method
zend_string * exclude_class_names[1]
ZEND_API void zend_alloc_ce_cache(zend_string *type_name)
ZEND_API void zend_map_ptr_extend(size_t last)
struct _zend_class_name zend_class_name
struct _zend_trait_precedence zend_trait_precedence
struct _zend_error_info zend_error_info
struct _zend_trait_alias zend_trait_alias
void zend_accel_error(int type, const char *format,...)
#define ACCEL_LOG_WARNING
zend_accel_hash_entry * zend_accel_hash_find_entry(zend_accel_hash *accel_hash, zend_string *key)
zend_accel_hash_entry * zend_accel_hash_update(zend_accel_hash *accel_hash, zend_string *key, bool indirect, void *data)
struct _zend_accel_hash_entry zend_accel_hash_entry
unsigned int zend_adler32(unsigned int checksum, unsigned char *buf, uint32_t len)
#define ZEND_MM_ALIGNED_SIZE(size)
struct _zend_ast_zval zend_ast_zval
struct _zend_ast_list zend_ast_list
struct _zend_attribute zend_attribute
zend_string_release_ex(func->internal_function.function_name, 0)
#define ZEND_PROPERTY_HOOK_COUNT
#define ZEND_ACC_IMMUTABLE
#define ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, node)
#define ZEND_FUNCTION_DTOR
#define ZEND_USER_FUNCTION
struct _zend_op_array zend_op_array
struct _zend_class_constant zend_class_constant
struct _zend_property_info zend_property_info
#define ZEND_ACC_ANON_CLASS
#define RT_CONSTANT(opline, node)
#define ZEND_ACC_HAS_RETURN_TYPE
struct _zend_arg_info zend_arg_info
#define ZEND_ACC_FILE_CACHED
#define ZEND_ACC_VARIADIC
ZEND_API zend_object_handlers zend_enum_object_handlers
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
#define IS_UNSERIALIZED(ptr)
#define SERIALIZE_STR(ptr)
#define IS_SERIALIZED(ptr)
int zend_file_cache_script_store(zend_persistent_script *script, bool in_shm)
void zend_file_cache_invalidate(zend_string *full_path)
zend_persistent_script * zend_file_cache_script_load(zend_file_handle *file_handle)
#define UNSERIALIZE_ATTRIBUTES(attributes)
struct _zend_file_cache_metainfo zend_file_cache_metainfo
#define SERIALIZE_PTR(ptr)
#define UNSERIALIZE_PTR(ptr)
void(* serialize_callback_t)(zval *zv, zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf)
void(* unserialize_callback_t)(zval *zv, zend_persistent_script *script, void *buf)
#define SERIALIZE_ATTRIBUTES(attributes)
#define UNSERIALIZE_STR(ptr)
#define HOOKED_ITERATOR_PLACEHOLDER
#define zend_file_cache_unlink
#define zend_file_cache_open
#define IS_SERIALIZED_INTERNED(ptr)
union _zend_function zend_function
#define HASH_FLAG_UNINITIALIZED
struct _zend_file_handle zend_file_handle
struct _zend_string zend_string
#define ZEND_MAP_PTR_INIT(ptr, val)
#define ZEND_MAP_PTR_NEW(ptr)
ZEND_API const zend_object_handlers std_object_handlers
uint32_t zend_accel_get_class_name_map_ptr(zend_string *type_name)
#define EXPECTED(condition)
#define UNEXPECTED(condition)
ZEND_API zend_object_iterator * zend_hooked_object_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
struct _zend_class_entry zend_class_entry
void zend_shared_alloc_lock(void)
void zend_shared_alloc_init_xlat_table(void)
void * zend_shared_alloc_get_xlat_entry(const void *key_pointer)
void zend_shared_alloc_unlock(void)
void zend_shared_alloc_destroy_xlat_table(void)
void zend_shared_alloc_register_xlat_entry(const void *key_pointer, const void *value)
void * zend_shared_alloc(size_t size)
#define _ZSTR_STRUCT_SIZE(len)
#define _ZSTR_HEADER_SIZE
ZEND_API char zend_system_id[32]
#define IS_STR_CLASS_NAME_MAP_PTR
struct _zend_ast_ref zend_ast_ref
#define ZEND_TYPE_NAME(t)
#define GC_SET_REFCOUNT(p, rc)
struct _zend_array HashTable
#define ZEND_TYPE_HAS_NAME(t)
void(* dtor_func_t)(zval *pDest)
#define ZEND_TYPE_HAS_LIST(t)
#define ZEND_TYPE_LIST_FOREACH_END()
#define Z_INDIRECT_P(zval_p)
#define HT_SET_DATA_ADDR(ht, ptr)
#define ZEND_TYPE_SET_PTR(t, _ptr)
#define ZEND_TYPE_LIST_FOREACH(list, type_ptr)
#define ZEND_TYPE_LIST(t)
struct _zend_ast zend_ast
#define GC_DEL_FLAGS(p, flags)
#define Z_ASTVAL_P(zval_p)
#define IS_STR_PERSISTENT
#define GC_ADD_FLAGS(p, flags)
ZEND_API void ZEND_FASTCALL zend_serialize_opcode_handler(zend_op *op)
ZEND_API void ZEND_FASTCALL zend_deserialize_opcode_handler(zend_op *op)
#define ZEND_ASSERT_CHECK
#define ZEND_SWITCH_STRING
#define ZEND_BIND_INIT_STATIC_OR_JMP
#define ZEND_JMP_FRAMELESS