]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-7.3' into PHP-7.4
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 29 Jul 2019 14:58:29 +0000 (16:58 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 29 Jul 2019 15:14:40 +0000 (17:14 +0200)
1  2 
Zend/zend_signal.c
ext/opcache/ZendAccelerator.c
main/main.c

Simple merge
index 0c3109ee50aa27346b03779314674868192bb4ae,80f94eaf28f2ab894140009077de1ad8138f9e7a..8efc340065cba65d344a1ff7928be5314fc73829
@@@ -3134,1433 -3127,6 +3143,1436 @@@ void accelerator_shm_read_unlock(void
        }
  }
  
 +/* Preloading */
 +static HashTable *preload_scripts = NULL;
 +static zend_op_array *(*preload_orig_compile_file)(zend_file_handle *file_handle, int type);
 +
 +static void preload_shutdown(void)
 +{
 +      zval *zv;
 +
 +#if 0
 +    if (EG(zend_constants)) {
 +              ZEND_HASH_REVERSE_FOREACH_VAL(EG(zend_constants), zv) {
 +                      zend_constant *c = Z_PTR_P(zv);
 +                      if (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) {
 +                              break;
 +                      }
 +              } ZEND_HASH_FOREACH_END_DEL();
 +      }
 +#endif
 +
 +    if (EG(function_table)) {
 +              ZEND_HASH_REVERSE_FOREACH_VAL(EG(function_table), zv) {
 +                      zend_function *func = Z_PTR_P(zv);
 +                      if (func->type == ZEND_INTERNAL_FUNCTION) {
 +                              break;
 +                      }
 +              } ZEND_HASH_FOREACH_END_DEL();
 +      }
 +
 +      if (EG(class_table)) {
 +              ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) {
 +                      zend_class_entry *ce = Z_PTR_P(zv);
 +                      if (ce->type == ZEND_INTERNAL_CLASS) {
 +                              break;
 +                      }
 +              } ZEND_HASH_FOREACH_END_DEL();
 +      }
 +}
 +
 +static void preload_activate(void)
 +{
 +      if (ZCSG(preload_script)->ping_auto_globals_mask) {
 +              zend_accel_set_auto_globals(ZCSG(preload_script)->ping_auto_globals_mask);
 +      }
 +}
 +
 +static void preload_restart(void)
 +{
 +      zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(ZCSG(preload_script)->script.filename), ZSTR_LEN(ZCSG(preload_script)->script.filename), 0, ZCSG(preload_script));
 +      if (ZCSG(saved_scripts)) {
 +              zend_persistent_script **p = ZCSG(saved_scripts);
 +              while (*p) {
 +                      zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL((*p)->script.filename), ZSTR_LEN((*p)->script.filename), 0, *p);
 +                      p++;
 +              }
 +      }
 +}
 +
 +static void preload_move_user_functions(HashTable *src, HashTable *dst)
 +{
 +      Bucket *p;
 +      dtor_func_t orig_dtor = src->pDestructor;
 +      zend_string *filename = NULL;
 +      int copy = 0;
 +
 +      src->pDestructor = NULL;
 +      zend_hash_extend(dst, dst->nNumUsed + src->nNumUsed, 0);
 +      ZEND_HASH_REVERSE_FOREACH_BUCKET(src, p) {
 +              zend_function *function = Z_PTR(p->val);
 +
 +              if (EXPECTED(function->type == ZEND_USER_FUNCTION)) {
 +                      if (function->op_array.filename != filename) {
 +                              filename = function->op_array.filename;
 +                              if (filename) {
 +                                      copy = zend_hash_exists(preload_scripts, filename);
 +                              } else {
 +                                      copy = 0;
 +                              }
 +                      }
 +                      if (copy) {
 +                              _zend_hash_append_ptr(dst, p->key, function);
 +                      } else {
 +                              orig_dtor(&p->val);
 +                      }
 +                      zend_hash_del_bucket(src, p);
 +              } else {
 +                      break;
 +              }
 +      } ZEND_HASH_FOREACH_END();
 +      src->pDestructor = orig_dtor;
 +}
 +
 +static void preload_move_user_classes(HashTable *src, HashTable *dst)
 +{
 +      Bucket *p;
 +      dtor_func_t orig_dtor = src->pDestructor;
 +      zend_string *filename = NULL;
 +      int copy = 0;
 +
 +      src->pDestructor = NULL;
 +      zend_hash_extend(dst, dst->nNumUsed + src->nNumUsed, 0);
 +      ZEND_HASH_REVERSE_FOREACH_BUCKET(src, p) {
 +              zend_class_entry *ce = Z_PTR(p->val);
 +
 +              if (EXPECTED(ce->type == ZEND_USER_CLASS)) {
 +                      if (ce->info.user.filename != filename) {
 +                              filename = ce->info.user.filename;
 +                              if (filename) {
 +                                      copy = zend_hash_exists(preload_scripts, filename);
 +                              } else {
 +                                      copy = 0;
 +                              }
 +                      }
 +                      if (copy) {
 +                              _zend_hash_append_ptr(dst, p->key, ce);
 +                      } else {
 +                              orig_dtor(&p->val);
 +                      }
 +                      zend_hash_del_bucket(src, p);
 +              } else {
 +                      break;
 +              }
 +      } ZEND_HASH_FOREACH_END();
 +      src->pDestructor = orig_dtor;
 +}
 +
 +static zend_op_array *preload_compile_file(zend_file_handle *file_handle, int type)
 +{
 +      zend_op_array *op_array = preload_orig_compile_file(file_handle, type);
 +
 +      if (op_array && op_array->refcount) {
 +              zend_persistent_script *script;
 +
 +              script = create_persistent_script();
 +              script->script.first_early_binding_opline = (uint32_t)-1;
 +              script->script.filename = zend_string_copy(op_array->filename);
 +              zend_string_hash_val(script->script.filename);
 +              script->script.main_op_array = *op_array;
 +
 +//???         efree(op_array->refcount);
 +              op_array->refcount = NULL;
 +
 +              if (op_array->static_variables &&
 +                  !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
 +                      GC_ADDREF(op_array->static_variables);
 +              }
 +
 +              zend_hash_add_ptr(preload_scripts, script->script.filename, script);
 +      }
 +
 +      return op_array;
 +}
 +
 +static void preload_sort_classes(void *base, size_t count, size_t siz, compare_func_t compare, swap_func_t swp) /* {{{ */
 +{
 +      Bucket *b1 = base;
 +      Bucket *b2;
 +      Bucket *end = b1 + count;
 +      Bucket tmp;
 +      zend_class_entry *ce, *p;
 +
 +      while (b1 < end) {
 +try_again:
 +              ce = (zend_class_entry*)Z_PTR(b1->val);
 +              if (ce->parent && (ce->ce_flags & ZEND_ACC_LINKED)) {
 +                      p = ce->parent;
 +                      if (p->type == ZEND_USER_CLASS) {
 +                              b2 = b1 + 1;
 +                              while (b2 < end) {
 +                                      if (p ==  Z_PTR(b2->val)) {
 +                                              tmp = *b1;
 +                                              *b1 = *b2;
 +                                              *b2 = tmp;
 +                                              goto try_again;
 +                                      }
 +                                      b2++;
 +                              }
 +                      }
 +              }
 +              if (ce->num_interfaces && (ce->ce_flags & ZEND_ACC_LINKED)) {
 +                      uint32_t i = 0;
 +                      for (i = 0; i < ce->num_interfaces; i++) {
 +                              p = ce->interfaces[i];
 +                              if (p->type == ZEND_USER_CLASS) {
 +                                      b2 = b1 + 1;
 +                                      while (b2 < end) {
 +                                              if (p ==  Z_PTR(b2->val)) {
 +                                                      tmp = *b1;
 +                                                      *b1 = *b2;
 +                                                      *b2 = tmp;
 +                                                      goto try_again;
 +                                              }
 +                                              b2++;
 +                                      }
 +                              }
 +                      }
 +              }
 +              b1++;
 +      }
 +}
 +
 +static void get_unresolved_initializer(zend_class_entry *ce, const char **kind, const char **name) {
 +      zend_string *key;
 +      zend_class_constant *c;
 +      zend_property_info *prop;
 +
 +      *kind = "unknown";
 +      *name = "";
 +
 +      ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
 +              if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
 +                      *kind = "constant ";
 +                      *name = ZSTR_VAL(key);
 +              }
 +      } ZEND_HASH_FOREACH_END();
 +      ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop) {
 +              zval *val;
 +              if (prop->flags & ZEND_ACC_STATIC) {
 +                      val = &ce->default_static_members_table[prop->offset];
 +              } else {
 +                      val = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop->offset)];
 +              }
 +              if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
 +                      *kind = (prop->flags & ZEND_ACC_STATIC) ? "static property $" : "property $";
 +                      *name = ZSTR_VAL(key);
 +              }
 +      } ZEND_HASH_FOREACH_END();
 +}
 +
 +static zend_bool preload_needed_types_known(zend_class_entry *ce);
 +static void get_unlinked_dependency(zend_class_entry *ce, const char **kind, const char **name) {
 +      zend_class_entry *p;
 +      *kind = "Unknown reason";
 +      *name = "";
 +
 +      if (ce->parent_name) {
 +              zend_string *key = zend_string_tolower(ce->parent_name);
 +              p = zend_hash_find_ptr(EG(class_table), key);
 +              zend_string_release(key);
 +              if (!p) {
 +                      *kind = "Unknown parent ";
 +                      *name = ZSTR_VAL(ce->parent_name);
 +                      return;
 +              }
 +              if (!(p->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
 +                      *kind = "Parent with unresolved initializers ";
 +                      *name = ZSTR_VAL(ce->parent_name);
 +                      return;
 +              }
 +              if (!(p->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED)) {
 +                      *kind = "Parent with unresolved property types ";
 +                      *name = ZSTR_VAL(ce->parent_name);
 +                      return;
 +              }
 +      }
 +
 +      if (ce->num_interfaces) {
 +              uint32_t i;
 +              for (i = 0; i < ce->num_interfaces; i++) {
 +                      p = zend_hash_find_ptr(EG(class_table), ce->interface_names[i].lc_name);
 +                      if (!p) {
 +                              *kind = "Unknown interface ";
 +                              *name = ZSTR_VAL(ce->interface_names[i].name);
 +                              return;
 +                      }
 +              }
 +      }
 +
 +      if (ce->num_traits) {
 +              uint32_t i;
 +              for (i = 0; i < ce->num_traits; i++) {
 +                      p = zend_hash_find_ptr(EG(class_table), ce->trait_names[i].lc_name);
 +                      if (!p) {
 +                              *kind = "Unknown trait ";
 +                              *name = ZSTR_VAL(ce->trait_names[i].name);
 +                              return;
 +                      }
 +              }
 +      }
 +
 +      if (!preload_needed_types_known(ce)) {
 +              *kind = "Unknown type dependencies";
 +              return;
 +      }
 +}
 +
 +static zend_bool preload_try_resolve_constants(zend_class_entry *ce)
 +{
 +      zend_bool ok, changed;
 +      zend_class_constant *c;
 +      zval *val;
 +
 +      EG(exception) = (void*)(uintptr_t)-1; /* prevent error reporting */
 +      CG(in_compilation) = 1; /* prevent autoloading */
 +      do {
 +              ok = 1;
 +              changed = 0;
 +              ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
 +                      val = &c->value;
 +                      if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
 +                              if (EXPECTED(zval_update_constant_ex(val, c->ce) == SUCCESS)) {
 +                                      changed = 1;
 +                              } else {
 +                                      ok = 0;
 +                              }
 +                      }
 +              } ZEND_HASH_FOREACH_END();
 +              if (ce->default_properties_count) {
 +                      uint32_t i;
 +                      for (i = 0; i < ce->default_properties_count; i++) {
 +                              val = &ce->default_properties_table[i];
 +                              if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
 +                                      zend_property_info *prop = ce->properties_info_table[i];
 +                                      if (UNEXPECTED(zval_update_constant_ex(val, prop->ce) != SUCCESS)) {
 +                                              ok = 0;
 +                                      }
 +                              }
 +                      }
 +              }
 +              if (ce->default_static_members_count) {
 +                      uint32_t count = ce->parent ? ce->default_static_members_count - ce->parent->default_static_members_count : ce->default_static_members_count;
 +
 +                      val = ce->default_static_members_table + ce->default_static_members_count - 1;
 +                      while (count) {
 +                              if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
 +                                      if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) {
 +                                              ok = 0;
 +                                      }
 +                              }
 +                              val--;
 +                              count--;
 +                      }
 +              }
 +      } while (changed && !ok);
 +      EG(exception) = NULL;
 +      CG(in_compilation) = 0;
 +
 +      return ok;
 +}
 +
 +static zend_bool preload_try_resolve_property_types(zend_class_entry *ce)
 +{
 +      zend_bool ok = 1;
 +      zend_property_info *prop;
 +      zend_class_entry *p;
 +
 +      if (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) {
 +              ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
 +                      zend_string *name, *lcname;
 +
 +                      if (!ZEND_TYPE_IS_NAME(prop->type)) {
 +                              continue;
 +                      }
 +
 +                      name = ZEND_TYPE_NAME(prop->type);
 +                      lcname = zend_string_tolower(name);
 +                      p = zend_hash_find_ptr(EG(class_table), lcname);
 +                      zend_string_release(lcname);
 +                      if (!p) {
 +                              ok = 0;
 +                              continue;
 +                      }
 +                      if (p != ce) {
 +#ifdef ZEND_WIN32
 +                              /* On Windows we can't link with internal class, because of ASLR */
 +                              if (p->type == ZEND_INTERNAL_CLASS) {
 +                                      ok = 0;
 +                                      continue;
 +                              }
 +#endif
 +                              if (!(p->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
 +                                      ok = 0;
 +                                      continue;
 +                              }
 +                              if (!(p->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED)) {
 +                                      ok = 0;
 +                                      continue;
 +                              }
 +                      }
 +
 +                      zend_string_release(name);
 +                      prop->type = ZEND_TYPE_ENCODE_CE(p, ZEND_TYPE_ALLOW_NULL(prop->type));
 +              } ZEND_HASH_FOREACH_END();
 +      }
 +
 +      return ok;
 +}
 +
 +static zend_bool preload_is_type_known(zend_class_entry *ce, zend_type type) {
 +      zend_string *name, *lcname;
 +      zend_bool known;
 +      if (!ZEND_TYPE_IS_NAME(type)) {
 +              return 1;
 +      }
 +
 +      name = ZEND_TYPE_NAME(type);
 +      if (zend_string_equals_literal_ci(name, "self") ||
 +              zend_string_equals_literal_ci(name, "parent") ||
 +              zend_string_equals_ci(name, ce->name)) {
 +              return 1;
 +      }
 +
 +      lcname = zend_string_tolower(name);
 +      known = zend_hash_exists(EG(class_table), lcname);
 +      zend_string_release(lcname);
 +      return known;
 +}
 +
 +static zend_bool preload_is_method_maybe_override(zend_class_entry *ce, zend_string *lcname) {
 +      zend_class_entry *p;
 +      if (ce->trait_aliases || ce->trait_precedences) {
 +              return 1;
 +      }
 +
 +      if (ce->parent_name) {
 +              zend_string *key = zend_string_tolower(ce->parent_name);
 +              p = zend_hash_find_ptr(EG(class_table), key);
 +              zend_string_release(key);
 +              if (zend_hash_exists(&p->function_table, lcname)) {
 +                      return 1;
 +              }
 +      }
 +
 +      if (ce->num_interfaces) {
 +              uint32_t i;
 +              for (i = 0; i < ce->num_interfaces; i++) {
 +                      zend_class_entry *p = zend_hash_find_ptr(EG(class_table), ce->interface_names[i].lc_name);
 +                      if (zend_hash_exists(&p->function_table, lcname)) {
 +                              return 1;
 +                      }
 +              }
 +      }
 +
 +      if (ce->num_traits) {
 +              uint32_t i;
 +              for (i = 0; i < ce->num_traits; i++) {
 +                      zend_class_entry *p = zend_hash_find_ptr(EG(class_table), ce->trait_names[i].lc_name);
 +                      if (zend_hash_exists(&p->function_table, lcname)) {
 +                              return 1;
 +                      }
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +static zend_bool preload_needed_types_known(zend_class_entry *ce) {
 +      zend_function *fptr;
 +      zend_string *lcname;
 +      ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, lcname, fptr) {
 +              uint32_t i;
 +              if (fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
 +                      if (!preload_is_type_known(ce, fptr->common.arg_info[-1].type) &&
 +                              preload_is_method_maybe_override(ce, lcname)) {
 +                              return 0;
 +                      }
 +              }
 +              for (i = 0; i < fptr->common.num_args; i++) {
 +                      if (!preload_is_type_known(ce, fptr->common.arg_info[i].type) &&
 +                              preload_is_method_maybe_override(ce, lcname)) {
 +                              return 0;
 +                      }
 +              }
 +      } ZEND_HASH_FOREACH_END();
 +      return 1;
 +}
 +
 +static void preload_link(void)
 +{
 +      zval *zv;
 +      zend_persistent_script *script;
 +      zend_class_entry *ce, *parent, *p;
 +      zend_string *key;
 +      zend_bool found, changed;
 +      uint32_t i;
 +      dtor_func_t orig_dtor;
 +      zend_function *function;
 +
 +      /* Resolve class dependencies */
 +      do {
 +              changed = 0;
 +
 +              ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) {
 +                      ce = Z_PTR_P(zv);
 +                      if (ce->type == ZEND_INTERNAL_CLASS) {
 +                              break;
 +                      }
 +                      if ((ce->ce_flags & (ZEND_ACC_TOP_LEVEL|ZEND_ACC_ANON_CLASS))
 +                       && !(ce->ce_flags & ZEND_ACC_LINKED)) {
 +
 +                              if (!(ce->ce_flags & ZEND_ACC_ANON_CLASS)) {
 +                                      key = zend_string_tolower(ce->name);
 +                                      if (zend_hash_exists(EG(class_table), key)) {
 +                                              zend_string_release(key);
 +                                              continue;
 +                                      }
 +                                      zend_string_release(key);
 +                              }
 +
 +                              parent = NULL;
 +
 +                              if (ce->parent_name) {
 +                                      key = zend_string_tolower(ce->parent_name);
 +                                      parent = zend_hash_find_ptr(EG(class_table), key);
 +                                      zend_string_release(key);
 +                                      if (!parent) continue;
 +#ifdef ZEND_WIN32
 +                                      /* On Windows we can't link with internal class, because of ASLR */
 +                                      if (parent->type == ZEND_INTERNAL_CLASS) continue;
 +#endif
 +                                      if (!(parent->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
 +                                              continue;
 +                                      }
 +                                      if (!(parent->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED)) {
 +                                              continue;
 +                                      }
 +                              }
 +
 +                              if (ce->num_interfaces) {
 +                                      found = 1;
 +                                      for (i = 0; i < ce->num_interfaces; i++) {
 +                                              p = zend_hash_find_ptr(EG(class_table), ce->interface_names[i].lc_name);
 +                                              if (!p) {
 +                                                      found = 0;
 +                                                      break;
 +                                              }
 +#ifdef ZEND_WIN32
 +                                              /* On Windows we can't link with internal class, because of ASLR */
 +                                              if (p->type == ZEND_INTERNAL_CLASS) {
 +                                                      found = 0;
 +                                                      break;
 +                                              }
 +#endif
 +                                              if (!(p->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
 +                                                      found = 0;
 +                                                      break;
 +                                              }
 +                                      }
 +                                      if (!found) continue;
 +                              }
 +
 +                              if (ce->num_traits) {
 +                                      found = 1;
 +                                      for (i = 0; i < ce->num_traits; i++) {
 +                                              p = zend_hash_find_ptr(EG(class_table), ce->trait_names[i].lc_name);
 +                                              if (!p) {
 +                                                      found = 0;
 +                                                      break;
 +                                              }
 +#ifdef ZEND_WIN32
 +                                              /* On Windows we can't link with internal class, because of ASLR */
 +                                              if (p->type == ZEND_INTERNAL_CLASS) {
 +                                                      found = 0;
 +                                                      break;
 +                                              }
 +#endif
 +                                      }
 +                                      if (!found) continue;
 +                              }
 +
 +                              /* TODO: This is much more restrictive than necessary. We only need to actually
 +                               * know the types for covariant checks, but don't need them if we can ensure
 +                               * compatibility through a simple string comparison. We could improve this using
 +                               * a more general version of zend_can_early_bind(). */
 +                              if (!preload_needed_types_known(ce)) {
 +                                      continue;
 +                              }
 +
 +                              zend_string *key = zend_string_tolower(ce->name);
 +                              zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, key);
 +                              zend_string_release(key);
 +
 +                              if (EXPECTED(zv)) {
 +                                      /* Set filename & lineno information for inheritance errors */
 +                                      CG(in_compilation) = 1;
 +                                      CG(compiled_filename) = ce->info.user.filename;
 +                                      if (ce->parent_name
 +                                       && !ce->num_interfaces
 +                                       && !ce->num_traits
 +                                       && (parent->type == ZEND_INTERNAL_CLASS
 +                                        || parent->info.user.filename == ce->info.user.filename)) {
 +                                              /* simulate early binding */
 +                                              CG(zend_lineno) = ce->info.user.line_end;
 +                                      } else {
 +                                              CG(zend_lineno) = ce->info.user.line_start;
 +                                      }
 +                                      zend_do_link_class(ce, NULL);
 +                                      CG(in_compilation) = 0;
 +                                      CG(compiled_filename) = NULL;
 +
 +                                      changed = 1;
 +                              }
 +                      }
 +                      if (ce->ce_flags & ZEND_ACC_LINKED) {
 +                              if (!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
 +                                      if ((ce->ce_flags & ZEND_ACC_TRAIT) /* don't update traits */
 +                                       || preload_try_resolve_constants(ce)) {
 +                                              ce->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
 +                                              changed = 1;
 +                                      }
 +                              }
 +
 +                              if (!(ce->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED)) {
 +                                      if ((ce->ce_flags & ZEND_ACC_TRAIT) /* don't update traits */
 +                                       || preload_try_resolve_property_types(ce)) {
 +                                              ce->ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED;
 +                                              changed = 1;
 +                                      }
 +                              }
 +                      }
 +              } ZEND_HASH_FOREACH_END();
 +      } while (changed);
 +
 +      /* Move unlinked clases (and with unresilved constants) back to scripts */
 +      orig_dtor = EG(class_table)->pDestructor;
 +      EG(class_table)->pDestructor = NULL;
 +      ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
 +              ce = Z_PTR_P(zv);
 +              if (ce->type == ZEND_INTERNAL_CLASS) {
 +                      break;
 +              }
 +              if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
 +                      zend_string *key = zend_string_tolower(ce->name);
 +                      if (zend_hash_exists(EG(class_table), key)) {
 +                              zend_error_at(
 +                                      E_WARNING, ZSTR_VAL(ce->info.user.filename), ce->info.user.line_start,
 +                                      "Can't preload already declared class %s", ZSTR_VAL(ce->name));
 +                      } else {
 +                              const char *kind, *name;
 +                              get_unlinked_dependency(ce, &kind, &name);
 +                              zend_error_at(
 +                                      E_WARNING, ZSTR_VAL(ce->info.user.filename), ce->info.user.line_start,
 +                                      "Can't preload unlinked class %s: %s%s",
 +                                      ZSTR_VAL(ce->name), kind, name);
 +                      }
 +                      zend_string_release(key);
 +              } else if (!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
 +                      const char *kind, *name;
 +                      get_unresolved_initializer(ce, &kind, &name);
 +                      zend_error_at(
 +                              E_WARNING, ZSTR_VAL(ce->info.user.filename), ce->info.user.line_start,
 +                              "Can't preload class %s with unresolved initializer for %s%s",
 +                              ZSTR_VAL(ce->name), kind, name);
 +              } else if (!(ce->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED)) {
 +                      zend_error_at(
 +                              E_WARNING, ZSTR_VAL(ce->info.user.filename), ce->info.user.line_start,
 +                              "Can't preload class %s with unresolved property types",
 +                              ZSTR_VAL(ce->name));
 +              } else {
 +                      continue;
 +              }
 +              ce->ce_flags &= ~ZEND_ACC_PRELOADED;
 +              ZEND_HASH_FOREACH_PTR(&ce->function_table, function) {
 +                      if (EXPECTED(function->type == ZEND_USER_FUNCTION)
 +                       && function->common.scope == ce) {
 +                              function->common.fn_flags &= ~ZEND_ACC_PRELOADED;
 +                      }
 +              } ZEND_HASH_FOREACH_END();
 +              script = zend_hash_find_ptr(preload_scripts, ce->info.user.filename);
 +              ZEND_ASSERT(script);
 +              zend_hash_add(&script->script.class_table, key, zv);
 +              ZVAL_UNDEF(zv);
 +              zend_string_release(key);
 +              EG(class_table)->nNumOfElements--;
 +      } ZEND_HASH_FOREACH_END();
 +      EG(class_table)->pDestructor = orig_dtor;
 +      zend_hash_rehash(EG(class_table));
 +
 +      /* Remove DECLARE opcodes */
 +      ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
 +              zend_op_array *op_array = &script->script.main_op_array;
 +              zend_op *opline = op_array->opcodes;
 +              zend_op *end = opline + op_array->last;
 +
 +              while (opline != end) {
 +                      switch (opline->opcode) {
 +                              case ZEND_DECLARE_CLASS:
 +                              case ZEND_DECLARE_CLASS_DELAYED:
 +                                      key = Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1);
 +                                      if (!zend_hash_exists(&script->script.class_table, key)) {
 +                                              MAKE_NOP(opline);
 +                                      }
 +                                      break;
 +                      }
 +                      opline++;
 +              }
 +
 +              if (op_array->fn_flags & ZEND_ACC_EARLY_BINDING) {
 +                      script->script.first_early_binding_opline = zend_build_delayed_early_binding_list(op_array);
 +                      if (script->script.first_early_binding_opline == (uint32_t)-1) {
 +                              op_array->fn_flags &= ~ZEND_ACC_EARLY_BINDING;
 +                      }
 +              }
 +      } ZEND_HASH_FOREACH_END();
 +}
 +
 +static zend_string *preload_resolve_path(zend_string *filename)
 +{
 +      if (is_stream_path(ZSTR_VAL(filename))) {
 +              return NULL;
 +      }
 +      return zend_resolve_path(ZSTR_VAL(filename), ZSTR_LEN(filename));
 +}
 +
 +static void preload_remove_empty_includes(void)
 +{
 +      zend_persistent_script *script;
 +      zend_bool changed;
 +
 +      /* mark all as empty */
 +      ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
 +              script->empty = 1;
 +      } ZEND_HASH_FOREACH_END();
 +
 +      /* find non empty scripts */
 +      do {
 +              changed = 0;
 +              ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
 +                      if (script->empty) {
 +                              int empty = 1;
 +                              zend_op *opline = script->script.main_op_array.opcodes;
 +                              zend_op *end = opline + script->script.main_op_array.last;
 +
 +                              while (opline < end) {
 +                                      if (opline->opcode == ZEND_INCLUDE_OR_EVAL &&
 +                                          opline->extended_value != ZEND_EVAL &&
 +                                          opline->op1_type == IS_CONST &&
 +                                          Z_TYPE_P(RT_CONSTANT(opline, opline->op1)) == IS_STRING) {
 +
 +                                              zend_string *resolved_path = preload_resolve_path(Z_STR_P(RT_CONSTANT(opline, opline->op1)));
 +
 +                                              if (resolved_path) {
 +                                                      zend_persistent_script *incl = zend_hash_find_ptr(preload_scripts, resolved_path);
 +                                                      zend_string_release(resolved_path);
 +                                                      if (!incl || !incl->empty) {
 +                                                              empty = 0;
 +                                                              break;
 +                                                      }
 +                                              } else {
 +                                                      empty = 0;
 +                                                      break;
 +                                              }
 +                                      } else if (opline->opcode != ZEND_NOP &&
 +                                                 opline->opcode != ZEND_RETURN &&
 +                                                 opline->opcode != ZEND_HANDLE_EXCEPTION) {
 +                                              empty = 0;
 +                                              break;
 +                                      }
 +                                      opline++;
 +                              }
 +                              if (!empty) {
 +                                      script->empty = 0;
 +                                      changed = 1;
 +                              }
 +                      }
 +              } ZEND_HASH_FOREACH_END();
 +      } while (changed);
 +
 +      /* remove empty includes */
 +      ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
 +              zend_op *opline = script->script.main_op_array.opcodes;
 +              zend_op *end = opline + script->script.main_op_array.last;
 +
 +              while (opline < end) {
 +                      if (opline->opcode == ZEND_INCLUDE_OR_EVAL &&
 +                          opline->extended_value != ZEND_EVAL &&
 +                          opline->op1_type == IS_CONST &&
 +                          Z_TYPE_P(RT_CONSTANT(opline, opline->op1)) == IS_STRING) {
 +
 +                              zend_string *resolved_path = preload_resolve_path(Z_STR_P(RT_CONSTANT(opline, opline->op1)));
 +
 +                              if (resolved_path) {
 +                                      zend_persistent_script *incl = zend_hash_find_ptr(preload_scripts, resolved_path);
 +                                      if (incl && incl->empty) {
 +                                              MAKE_NOP(opline);
 +                                      } else {
 +                                              if (!IS_ABSOLUTE_PATH(Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), Z_STRLEN_P(RT_CONSTANT(opline, opline->op1)))) {
 +                                                      /* replace relative patch with absolute one */
 +                                                      zend_string_release(Z_STR_P(RT_CONSTANT(opline, opline->op1)));
 +                                                      ZVAL_STR_COPY(RT_CONSTANT(opline, opline->op1), resolved_path);
 +                                              }
 +                                      }
 +                                      zend_string_release(resolved_path);
 +                              }
 +                      }
 +                      opline++;
 +              }
 +      } ZEND_HASH_FOREACH_END();
 +}
 +
 +static void preload_register_trait_methods(zend_class_entry *ce) {
 +      zend_op_array *op_array;
 +      ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
 +              if (!(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
 +                      zend_shared_alloc_register_xlat_entry(op_array->opcodes, op_array);
 +              }
 +      } ZEND_HASH_FOREACH_END();
 +}
 +
 +static void preload_fix_trait_methods(zend_class_entry *ce)
 +{
 +      zend_op_array *op_array;
 +
 +      ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
 +              if (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE) {
 +                      zend_op_array *orig_op_array = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
 +                      if (orig_op_array) {
 +                              zend_class_entry *scope = op_array->scope;
 +                              uint32_t fn_flags = op_array->fn_flags;
 +                              zend_function *prototype = op_array->prototype;
 +                              HashTable *ht = op_array->static_variables;
 +                              *op_array = *orig_op_array;
 +                              op_array->scope = scope;
 +                              op_array->fn_flags = fn_flags;
 +                              op_array->prototype = prototype;
 +                              op_array->static_variables = ht;
 +                      }
 +              }
 +      } ZEND_HASH_FOREACH_END();
 +}
 +
 +static int preload_optimize(zend_persistent_script *script)
 +{
 +      zend_class_entry *ce;
 +
 +      zend_shared_alloc_init_xlat_table();
 +
 +      ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) {
 +              if (ce->ce_flags & ZEND_ACC_TRAIT) {
 +                      preload_register_trait_methods(ce);
 +              }
 +      } ZEND_HASH_FOREACH_END();
 +
 +      ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
 +              ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) {
 +                      if (ce->ce_flags & ZEND_ACC_TRAIT) {
 +                              preload_register_trait_methods(ce);
 +                      }
 +              } ZEND_HASH_FOREACH_END();
 +      } ZEND_HASH_FOREACH_END();
 +
 +      if (!zend_optimize_script(&script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
 +              return FAILURE;
 +      }
 +
 +      ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) {
 +              if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) {
 +                      preload_fix_trait_methods(ce);
 +              }
 +      } ZEND_HASH_FOREACH_END();
 +
 +      ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
 +              ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) {
 +                      if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) {
 +                              preload_fix_trait_methods(ce);
 +                      }
 +              } ZEND_HASH_FOREACH_END();
 +      } ZEND_HASH_FOREACH_END();
 +
 +      zend_shared_alloc_destroy_xlat_table();
 +
 +      ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
 +              if (!zend_optimize_script(&script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
 +                      return FAILURE;
 +              }
 +      } ZEND_HASH_FOREACH_END();
 +      return SUCCESS;
 +}
 +
 +static zend_persistent_script* preload_script_in_shared_memory(zend_persistent_script *new_persistent_script)
 +{
 +      zend_accel_hash_entry *bucket;
 +      uint32_t memory_used;
 +      uint32_t checkpoint;
 +
 +      if (zend_accel_hash_is_full(&ZCSG(hash))) {
 +              zend_accel_error(ACCEL_LOG_FATAL, "Not enough entries in hash table for preloading. Consider increasing the value for the opcache.max_accelerated_files directive in php.ini.");
 +              return NULL;
 +      }
 +
 +      checkpoint = zend_shared_alloc_checkpoint_xlat_table();
 +
 +      /* Calculate the required memory size */
 +      memory_used = zend_accel_script_persist_calc(new_persistent_script, NULL, 0, 1);
 +
 +      /* Allocate shared memory */
 +#if defined(__AVX__) || defined(__SSE2__)
 +      /* Align to 64-byte boundary */
 +      ZCG(mem) = zend_shared_alloc(memory_used + 64);
 +      if (ZCG(mem)) {
 +              ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
 +#if defined(__x86_64__)
 +              memset(ZCG(mem), 0, memory_used);
 +#elif defined(__AVX__)
 +              {
 +                      char *p = (char*)ZCG(mem);
 +                      char *end = p + memory_used;
 +                      __m256i ymm0 = _mm256_setzero_si256();
 +
 +                      while (p < end) {
 +                              _mm256_store_si256((__m256i*)p, ymm0);
 +                              _mm256_store_si256((__m256i*)(p+32), ymm0);
 +                              p += 64;
 +                      }
 +              }
 +#else
 +              {
 +                      char *p = (char*)ZCG(mem);
 +                      char *end = p + memory_used;
 +                      __m128i xmm0 = _mm_setzero_si128();
 +
 +                      while (p < end) {
 +                              _mm_store_si128((__m128i*)p, xmm0);
 +                              _mm_store_si128((__m128i*)(p+16), xmm0);
 +                              _mm_store_si128((__m128i*)(p+32), xmm0);
 +                              _mm_store_si128((__m128i*)(p+48), xmm0);
 +                              p += 64;
 +                      }
 +              }
 +#endif
 +      }
 +#else
 +      ZCG(mem) = zend_shared_alloc(memory_used);
 +      if (ZCG(mem)) {
 +              memset(ZCG(mem), 0, memory_used);
 +      }
 +#endif
 +      if (!ZCG(mem)) {
 +              zend_accel_error(ACCEL_LOG_FATAL, "Not enough shared memory for preloading. Consider increasing the value for the opcache.memory_consumption directive in php.ini.");
 +              return NULL;
 +      }
 +
 +      zend_shared_alloc_restore_xlat_table(checkpoint);
 +
 +      /* Copy into shared memory */
 +      new_persistent_script = zend_accel_script_persist(new_persistent_script, NULL, 0, 1);
 +
 +      new_persistent_script->is_phar = is_phar_file(new_persistent_script->script.filename);
 +
 +      /* Consistency check */
 +      if ((char*)new_persistent_script->mem + new_persistent_script->size != (char*)ZCG(mem)) {
 +              zend_accel_error(
 +                      ((char*)new_persistent_script->mem + new_persistent_script->size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING,
 +                      "Internal error: wrong size calculation: %s start=" ZEND_ADDR_FMT ", end=" ZEND_ADDR_FMT ", real=" ZEND_ADDR_FMT "\n",
 +                      ZSTR_VAL(new_persistent_script->script.filename),
 +                      (size_t)new_persistent_script->mem,
 +                      (size_t)((char *)new_persistent_script->mem + new_persistent_script->size),
 +                      (size_t)ZCG(mem));
 +      }
 +
 +      new_persistent_script->dynamic_members.checksum = zend_accel_script_checksum(new_persistent_script);
 +
 +      /* store script structure in the hash table */
 +      bucket = zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(new_persistent_script->script.filename), ZSTR_LEN(new_persistent_script->script.filename), 0, new_persistent_script);
 +      if (bucket) {
 +              zend_accel_error(ACCEL_LOG_INFO, "Cached script '%s'", ZSTR_VAL(new_persistent_script->script.filename));
 +      }
 +
 +      new_persistent_script->dynamic_members.memory_consumption = ZEND_ALIGNED_SIZE(new_persistent_script->size);
 +
 +      return new_persistent_script;
 +}
 +
 +static void preload_load(void)
 +{
 +      /* Load into process tables */
 +      if (zend_hash_num_elements(&ZCSG(preload_script)->script.function_table)) {
 +              Bucket *p = ZCSG(preload_script)->script.function_table.arData;
 +              Bucket *end = p + ZCSG(preload_script)->script.function_table.nNumUsed;
 +
 +              for (; p != end; p++) {
 +                      _zend_hash_append_ptr_ex(CG(function_table), p->key, Z_PTR(p->val), 1);
 +              }
 +      }
 +
 +      if (zend_hash_num_elements(&ZCSG(preload_script)->script.class_table)) {
 +              Bucket *p = ZCSG(preload_script)->script.class_table.arData;
 +              Bucket *end = p + ZCSG(preload_script)->script.class_table.nNumUsed;
 +
 +              for (; p != end; p++) {
 +                      _zend_hash_append_ptr_ex(CG(class_table), p->key, Z_PTR(p->val), 1);
 +              }
 +      }
 +
 +      if (EG(zend_constants)) {
 +              EG(persistent_constants_count) = EG(zend_constants)->nNumUsed;
 +      }
 +      if (EG(function_table)) {
 +              EG(persistent_functions_count) = EG(function_table)->nNumUsed;
 +      }
 +      if (EG(class_table)) {
 +              EG(persistent_classes_count)   = EG(class_table)->nNumUsed;
 +      }
 +      CG(map_ptr_last) = ZCSG(map_ptr_last);
 +}
 +
 +static int accel_preload(const char *config)
 +{
 +      zend_file_handle file_handle;
 +      int ret;
 +      uint32_t orig_compiler_options;
 +      char *orig_open_basedir;
 +      size_t orig_map_ptr_last;
 +      zval *zv;
 +
 +      ZCG(enabled) = 0;
 +      ZCG(accelerator_enabled) = 0;
 +      orig_open_basedir = PG(open_basedir);
 +      PG(open_basedir) = NULL;
 +      preload_orig_compile_file = accelerator_orig_compile_file;
 +      accelerator_orig_compile_file = preload_compile_file;
 +
 +      orig_compiler_options = CG(compiler_options);
 +      CG(compiler_options) |= ZEND_COMPILE_PRELOAD;
 +      CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY;
 +//    CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES;
 +      CG(compiler_options) |= ZEND_COMPILE_DELAYED_BINDING;
 +      CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION;
 +//    CG(compiler_options) |= ZEND_COMPILE_IGNORE_OTHER_FILES;
 +
 +      orig_map_ptr_last = CG(map_ptr_last);
 +
 +      /* Compile and execute proloading script */
 +      zend_stream_init_filename(&file_handle, (char *) config);
 +
 +      preload_scripts = emalloc(sizeof(HashTable));
 +      zend_hash_init(preload_scripts, 0, NULL, NULL, 0);
 +
 +      zend_try {
 +              zend_op_array *op_array;
 +
 +              ret = SUCCESS;
 +              op_array = zend_compile_file(&file_handle, ZEND_REQUIRE);
 +              if (file_handle.opened_path) {
 +                      zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path);
 +              }
 +              zend_destroy_file_handle(&file_handle);
 +              if (op_array) {
 +                      zend_execute(op_array, NULL);
 +                      zend_exception_restore();
 +                      if (UNEXPECTED(EG(exception))) {
 +                              if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
 +                                      zend_user_exception_handler();
 +                              }
 +                              if (EG(exception)) {
 +                                      zend_exception_error(EG(exception), E_ERROR);
 +                                      CG(unclean_shutdown) = 1;
 +                                      ret = FAILURE;
 +                              }
 +                      }
 +                      destroy_op_array(op_array);
 +                      efree_size(op_array, sizeof(zend_op_array));
 +              } else {
 +                      CG(unclean_shutdown) = 1;
 +                      ret = FAILURE;
 +              }
 +      } zend_catch {
 +              ret = FAILURE;
 +      } zend_end_try();
 +
 +      CG(compiler_options) = orig_compiler_options;
 +      PG(open_basedir) = orig_open_basedir;
 +      accelerator_orig_compile_file = preload_orig_compile_file;
 +      ZCG(enabled) = 1;
 +
 +      zend_destroy_file_handle(&file_handle);
 +
 +      if (ret == SUCCESS) {
 +              zend_persistent_script *script;
 +              zend_string *filename;
 +              int ping_auto_globals_mask;
 +              int i;
 +              zend_class_entry *ce;
 +              zend_op_array *op_array;
 +
 +              if (PG(auto_globals_jit)) {
 +                      ping_auto_globals_mask = zend_accel_get_auto_globals();
 +              } else {
 +                      ping_auto_globals_mask = zend_accel_get_auto_globals_no_jit();
 +              }
 +
 +              /* Cleanup executor */
 +              EG(flags) |= EG_FLAGS_IN_SHUTDOWN;
 +
 +              php_call_shutdown_functions();
 +              zend_call_destructors();
 +              php_free_shutdown_functions();
 +
 +              /* Release stored values to avoid dangling pointers */
 +              zend_hash_graceful_reverse_destroy(&EG(symbol_table));
 +              zend_hash_init(&EG(symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
 +
 +#if ZEND_DEBUG
 +              if (gc_enabled() && !CG(unclean_shutdown)) {
 +                      gc_collect_cycles();
 +              }
 +#endif
 +
 +              zend_objects_store_free_object_storage(&EG(objects_store), 1);
 +
 +              /* Cleanup static variables of preloaded functions */
 +              ZEND_HASH_REVERSE_FOREACH_VAL(EG(function_table), zv) {
 +                      zend_op_array *op_array = Z_PTR_P(zv);
 +                      if (op_array->type == ZEND_INTERNAL_FUNCTION) {
 +                              break;
 +                      }
 +                      ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_PRELOADED);
 +                      if (op_array->static_variables) {
 +                              HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
 +                              if (ht) {
 +                                      ZEND_ASSERT(GC_REFCOUNT(ht) == 1);
 +                                      zend_array_destroy(ht);
 +                                      ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
 +                              }
 +                      }
 +              } ZEND_HASH_FOREACH_END();
 +
 +              /* Cleanup static properties and variables of preloaded classes */
 +              ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) {
 +                      zend_class_entry *ce = Z_PTR_P(zv);
 +                      if (ce->type == ZEND_INTERNAL_CLASS) {
 +                              break;
 +                      }
 +                      ZEND_ASSERT(ce->ce_flags & ZEND_ACC_PRELOADED);
 +                      if (ce->default_static_members_count) {
 +                              zend_cleanup_internal_class_data(ce);
 +                      }
 +                      if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
 +                              zend_op_array *op_array;
 +
 +                              ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
 +                                      if (op_array->type == ZEND_USER_FUNCTION) {
 +                                              if (op_array->static_variables) {
 +                                                      HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
 +                                                      if (ht) {
 +                                                              ZEND_ASSERT(GC_REFCOUNT(ht) == 1);
 +                                                              zend_array_destroy(ht);
 +                                                              ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
 +                                                      }
 +                                              }
 +                                      }
 +                              } ZEND_HASH_FOREACH_END();
 +                      }
 +              } ZEND_HASH_FOREACH_END();
 +
 +              CG(map_ptr_last) = orig_map_ptr_last;
 +
 +              /* Inheritance errors may be thrown during linking */
 +              zend_try {
 +                      preload_link();
 +              } zend_catch {
 +                      CG(map_ptr_last) = orig_map_ptr_last;
 +                      ret = FAILURE;
 +                      goto finish;
 +              } zend_end_try();
 +
 +              preload_remove_empty_includes();
 +
 +              /* Don't preload constants */
 +              if (EG(zend_constants)) {
 +                      zend_string *key;
 +                      zval *zv;
 +
 +                      /* Remember __COMPILER_HALT_OFFSET__(s) */
 +                      ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
 +                              zend_execute_data *orig_execute_data = EG(current_execute_data);
 +                              zend_execute_data fake_execute_data;
 +                              zval *offset;
 +
 +                              memset(&fake_execute_data, 0, sizeof(fake_execute_data));
 +                              fake_execute_data.func = (zend_function*)&script->script.main_op_array;
 +                              EG(current_execute_data) = &fake_execute_data;
 +                              if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
 +                                      script->compiler_halt_offset = Z_LVAL_P(offset);
 +                              }
 +                              EG(current_execute_data) = orig_execute_data;
 +                      } ZEND_HASH_FOREACH_END();
 +
 +                      ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) {
 +                              zend_constant *c = Z_PTR_P(zv);
 +                              if (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) {
 +                                      break;
 +                              }
 +                              EG(zend_constants)->pDestructor(zv);
 +                              zend_string_release(key);
 +                      } ZEND_HASH_FOREACH_END_DEL();
 +              }
 +
 +              script = create_persistent_script();
 +              script->ping_auto_globals_mask = ping_auto_globals_mask;
 +
 +              /* Store all functions and classes in a single pseudo-file */
 +              filename = zend_string_init("$PRELOAD$", strlen("$PRELOAD$"), 0);
 +#if ZEND_USE_ABS_CONST_ADDR
 +              init_op_array(&script->script.main_op_array, ZEND_USER_FUNCTION, 1);
 +#else
 +              init_op_array(&script->script.main_op_array, ZEND_USER_FUNCTION, 2);
 +#endif
 +              script->script.main_op_array.last = 1;
 +              script->script.main_op_array.last_literal = 1;
 +#if ZEND_USE_ABS_CONST_ADDR
 +              script->script.main_op_array.literals = (zval*)emalloc(sizeof(zval));
 +#else
 +              script->script.main_op_array.literals = (zval*)(script->script.main_op_array.opcodes + 1);
 +#endif
 +              ZVAL_NULL(script->script.main_op_array.literals);
 +              memset(script->script.main_op_array.opcodes, 0, sizeof(zend_op));
 +              script->script.main_op_array.opcodes[0].opcode = ZEND_RETURN;
 +              script->script.main_op_array.opcodes[0].op1_type = IS_CONST;
 +              script->script.main_op_array.opcodes[0].op1.constant = 0;
 +              ZEND_PASS_TWO_UPDATE_CONSTANT(&script->script.main_op_array, script->script.main_op_array.opcodes, script->script.main_op_array.opcodes[0].op1);
 +
 +              script->script.main_op_array.filename = filename;
 +              script->script.filename = zend_string_copy(filename);
 +
 +              script->script.first_early_binding_opline = (uint32_t)-1;
 +
 +              preload_move_user_functions(CG(function_table), &script->script.function_table);
 +              preload_move_user_classes(CG(class_table), &script->script.class_table);
 +
 +              zend_hash_sort_ex(&script->script.class_table, preload_sort_classes, NULL, 0);
 +
 +              if (preload_optimize(script) != SUCCESS) {
 +                      zend_accel_error(ACCEL_LOG_FATAL, "Optimization error during preloading!");
 +                      return FAILURE;
 +              }
 +
 +              zend_shared_alloc_init_xlat_table();
 +
 +              HANDLE_BLOCK_INTERRUPTIONS();
 +              SHM_UNPROTECT();
 +
 +              /* Store method names first, because they may be shared between preloaded and non-preloaded classes */
 +              ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) {
 +                      ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
 +                              zend_string *new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name);
 +
 +                              if (!new_name) {
 +                                      new_name = accel_new_interned_string(op_array->function_name);
 +                                      zend_shared_alloc_register_xlat_entry(op_array->function_name, new_name);
 +                              }
 +                              op_array->function_name = new_name;
 +                      } ZEND_HASH_FOREACH_END();
 +              } ZEND_HASH_FOREACH_END();
 +
 +              ZCSG(preload_script) = preload_script_in_shared_memory(script);
 +
 +              SHM_PROTECT();
 +              HANDLE_UNBLOCK_INTERRUPTIONS();
 +
 +              zend_string_release(filename);
 +
 +              ZEND_ASSERT(ZCSG(preload_script)->arena_size == 0);
 +
 +              preload_load();
 +
 +              /* Store individual scripts with unlinked classes */
 +              HANDLE_BLOCK_INTERRUPTIONS();
 +              SHM_UNPROTECT();
 +
 +              i = 0;
 +              ZCSG(saved_scripts) = zend_shared_alloc((zend_hash_num_elements(preload_scripts) + 1) * sizeof(void*));
 +              ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
 +                      if (zend_hash_num_elements(&script->script.class_table) > 1) {
 +                              zend_hash_sort_ex(&script->script.class_table, preload_sort_classes, NULL, 0);
 +                      }
 +                      ZCSG(saved_scripts)[i++] = preload_script_in_shared_memory(script);
 +              } ZEND_HASH_FOREACH_END();
 +              ZCSG(saved_scripts)[i] = NULL;
 +
 +              zend_shared_alloc_save_state();
 +              accel_interned_strings_save_state();
 +
 +              SHM_PROTECT();
 +              HANDLE_UNBLOCK_INTERRUPTIONS();
 +
 +              zend_shared_alloc_destroy_xlat_table();
 +      } else {
 +              CG(map_ptr_last) = orig_map_ptr_last;
 +      }
 +
 +finish:
 +      zend_hash_destroy(preload_scripts);
 +      efree(preload_scripts);
 +      preload_scripts = NULL;
 +
 +      return ret;
 +}
 +
 +static size_t preload_ub_write(const char *str, size_t str_length)
 +{
 +      return fwrite(str, 1, str_length, stdout);
 +}
 +
 +static void preload_flush(void *server_context)
 +{
 +      fflush(stdout);
 +}
 +
 +static int preload_header_handler(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s)
 +{
 +      return 0;
 +}
 +
 +static int preload_send_headers(sapi_headers_struct *sapi_headers)
 +{
 +      return SAPI_HEADER_SENT_SUCCESSFULLY;
 +}
 +
 +static void preload_send_header(sapi_header_struct *sapi_header, void *server_context)
 +{
 +}
 +
 +static int accel_finish_startup(void)
 +{
 +      if (!ZCG(enabled) || !accel_startup_ok) {
 +              return SUCCESS;
 +      }
 +
 +      if (ZCG(accel_directives).preload && *ZCG(accel_directives).preload) {
 +              int ret = SUCCESS;
 +              int rc;
 +              int orig_error_reporting;
 +
 +              int (*orig_activate)(TSRMLS_D) = sapi_module.activate;
 +              int (*orig_deactivate)(TSRMLS_D) = sapi_module.deactivate;
 +              void (*orig_register_server_variables)(zval *track_vars_array TSRMLS_DC) = sapi_module.register_server_variables;
 +              int (*orig_header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC) = sapi_module.header_handler;
 +              int (*orig_send_headers)(sapi_headers_struct *sapi_headers TSRMLS_DC) = sapi_module.send_headers;
 +              void (*orig_send_header)(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC)= sapi_module.send_header;
 +              char *(*orig_getenv)(char *name, size_t name_len TSRMLS_DC) = sapi_module.getenv;
 +              size_t (*orig_ub_write)(const char *str, size_t str_length) = sapi_module.ub_write;
 +              void (*orig_flush)(void *server_context) = sapi_module.flush;
 +#ifdef ZEND_SIGNALS
 +              zend_bool old_reset_signals = SIGG(reset);
 +#endif
 +
 +              if (UNEXPECTED(file_cache_only)) {
 +                      zend_accel_error(ACCEL_LOG_WARNING, "Preloading doesn't work in \"file_cache_only\" mode");
 +                      return SUCCESS;
 +              }
 +
 +              /* exclusive lock */
 +              zend_shared_alloc_lock();
 +
 +              if (ZCSG(preload_script)) {
 +                      /* Preloading was done in another process */
 +                      preload_load();
 +                      zend_shared_alloc_unlock();
 +                      return SUCCESS;
 +              }
 +
 +              sapi_module.activate = NULL;
 +              sapi_module.deactivate = NULL;
 +              sapi_module.register_server_variables = NULL;
 +              sapi_module.header_handler = preload_header_handler;
 +              sapi_module.send_headers = preload_send_headers;
 +              sapi_module.send_header = preload_send_header;
 +              sapi_module.getenv = NULL;
 +              sapi_module.ub_write = preload_ub_write;
 +              sapi_module.flush = preload_flush;
 +
 +              zend_interned_strings_switch_storage(1);
 +
 +#ifdef ZEND_SIGNALS
 +              SIGG(reset) = 0;
 +#endif
 +
 +              orig_error_reporting = EG(error_reporting);
 +              EG(error_reporting) = 0;
 +
 +              rc = php_request_startup();
 +
 +              EG(error_reporting) = orig_error_reporting;
 +
 +              if (rc == SUCCESS) {
 +                      zend_bool orig_report_memleaks;
 +
 +                      /* don't send headers */
 +                      SG(headers_sent) = 1;
 +                      SG(request_info).no_headers = 1;
 +                      php_output_set_status(0);
 +
 +                      ZCG(auto_globals_mask) = 0;
 +                      ZCG(request_time) = (time_t)sapi_get_request_time();
 +                      ZCG(cache_opline) = NULL;
 +                      ZCG(cache_persistent_script) = NULL;
 +                      ZCG(include_path_key_len) = 0;
 +                      ZCG(include_path_check) = 1;
 +
 +                      ZCG(cwd) = NULL;
 +                      ZCG(cwd_key_len) = 0;
 +                      ZCG(cwd_check) = 1;
 +
 +                      if (accel_preload(ZCG(accel_directives).preload) != SUCCESS) {
 +                              ret = FAILURE;
 +                      }
 +
 +                      orig_report_memleaks = PG(report_memleaks);
 +                      PG(report_memleaks) = 0;
++                      /* We may not have registered signal handlers due to SIGG(reset)=0, so
++                       * also disable the check that they are registered. */
++                      SIGG(check) = 0;
 +                      php_request_shutdown(NULL); /* calls zend_shared_alloc_unlock(); */
 +                      PG(report_memleaks) = orig_report_memleaks;
 +              } else {
 +                      zend_shared_alloc_unlock();
 +                      ret = FAILURE;
 +              }
 +#ifdef ZEND_SIGNALS
 +              SIGG(reset) = old_reset_signals;
 +#endif
 +
 +              sapi_module.activate = orig_activate;
 +              sapi_module.deactivate = orig_deactivate;
 +              sapi_module.register_server_variables = orig_register_server_variables;
 +              sapi_module.header_handler = orig_header_handler;
 +              sapi_module.send_headers = orig_send_headers;
 +              sapi_module.send_header = orig_send_header;
 +              sapi_module.getenv = orig_getenv;
 +              sapi_module.ub_write = orig_ub_write;
 +              sapi_module.flush = orig_flush;
 +
 +              sapi_activate();
 +
 +              return ret;
 +      }
 +
 +      return SUCCESS;
 +}
 +
  ZEND_EXT_API zend_extension zend_extension_entry = {
        ACCELERATOR_PRODUCT_NAME,               /* name */
        PHP_VERSION,                                                    /* version */
diff --cc main/main.c
index 9c8e83cc42376c74f533512377cf248c00dd988f,f729c2e27578e1016b86924b394a1d38c73b4294..5822cbfa217b8a1e0e930fc7d2b3ac1fe083d68e
@@@ -1940,6 -1953,16 +1940,11 @@@ void php_request_shutdown(void *dummy
                shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0);
        } zend_end_try();
  
 -      /* 16. Reset max_execution_time */
 -      zend_try {
 -              zend_unset_timeout();
 -      } zend_end_try();
 -
 -      /* 17. Deactivate Zend signals */
++      /* 16. Deactivate Zend signals */
+ #ifdef ZEND_SIGNALS
+       zend_signal_deactivate();
+ #endif
  #ifdef PHP_WIN32
        if (PG(com_initialized)) {
                CoUninitialize();