diff --git a/Zend/zend.c b/Zend/zend.c index 0498d59ba0809..dd1e3a337a40e 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -85,7 +85,6 @@ ZEND_API char *(*zend_getenv)(const char *name, size_t name_len); ZEND_API zend_string *(*zend_resolve_path)(zend_string *filename); ZEND_API zend_result (*zend_post_startup_cb)(void) = NULL; ZEND_API void (*zend_post_shutdown_cb)(void) = NULL; -ZEND_API zend_result (*zend_preload_autoload)(zend_string *filename) = NULL; /* This callback must be signal handler safe! */ void (*zend_on_timeout)(int seconds); diff --git a/Zend/zend.h b/Zend/zend.h index 8cebe80d94b12..eeacc91eb0a9f 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -332,9 +332,6 @@ extern ZEND_API zend_string *(*zend_resolve_path)(zend_string *filename); extern ZEND_API zend_result (*zend_post_startup_cb)(void); extern ZEND_API void (*zend_post_shutdown_cb)(void); -/* Callback for loading of not preloaded part of the script */ -extern ZEND_API zend_result (*zend_preload_autoload)(zend_string *filename); - ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); /* For custom format specifiers like H */ diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 09e58aa98aedd..3e0936216a60c 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1104,9 +1104,16 @@ ZEND_API zend_class_entry *zend_bind_class_in_slot( zval *class_table_slot, zval *lcname, zend_string *lc_parent_name) { zend_class_entry *ce = Z_PTR_P(class_table_slot); - zval *zv = zend_hash_set_bucket_key( - EG(class_table), (Bucket *) class_table_slot, Z_STR_P(lcname)); - if (UNEXPECTED(!zv)) { + bool is_preloaded = + (ce->ce_flags & ZEND_ACC_PRELOADED) && !(CG(compiler_options) & ZEND_COMPILE_PRELOAD); + bool success; + if (EXPECTED(!is_preloaded)) { + success = zend_hash_set_bucket_key(EG(class_table), (Bucket*) class_table_slot, Z_STR_P(lcname)) != NULL; + } else { + /* If preloading is used, don't replace the existing bucket, add a new one. */ + success = zend_hash_add_ptr(EG(class_table), Z_STR_P(lcname), ce) != NULL; + } + if (UNEXPECTED(!success)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name)); return NULL; } @@ -1120,9 +1127,13 @@ ZEND_API zend_class_entry *zend_bind_class_in_slot( return ce; } - /* Reload bucket pointer, the hash table may have been reallocated */ - zv = zend_hash_find(EG(class_table), Z_STR_P(lcname)); - zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1)); + if (!is_preloaded) { + /* Reload bucket pointer, the hash table may have been reallocated */ + zval *zv = zend_hash_find(EG(class_table), Z_STR_P(lcname)); + zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1)); + } else { + zend_hash_del(EG(class_table), Z_STR_P(lcname)); + } return NULL; } @@ -1137,23 +1148,9 @@ ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name) /* if (UNEXPECTED(!zv)) { ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname)); - if (ce) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name)); - return FAILURE; - } else { - do { - ZEND_ASSERT(EG(current_execute_data)->func->op_array.fn_flags & ZEND_ACC_PRELOADED); - if (zend_preload_autoload - && zend_preload_autoload(EG(current_execute_data)->func->op_array.filename) == SUCCESS) { - zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(rtd_key)); - if (EXPECTED(zv != NULL)) { - break; - } - } - zend_error_noreturn(E_ERROR, "Class %s wasn't preloaded", Z_STRVAL_P(lcname)); - return FAILURE; - } while (0); - } + ZEND_ASSERT(ce); + zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name)); + return FAILURE; } /* Register the derived class */ diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 9d20c0865b359..b3f9823bf9f55 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -3017,12 +3017,19 @@ static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_e static zend_always_inline bool register_early_bound_ce(zval *delayed_early_binding, zend_string *lcname, zend_class_entry *ce) { if (delayed_early_binding) { - if (UNEXPECTED(zend_hash_set_bucket_key(EG(class_table), (Bucket *)delayed_early_binding, lcname) == NULL)) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name)); - return false; + if (EXPECTED(!(ce->ce_flags & ZEND_ACC_PRELOADED))) { + if (zend_hash_set_bucket_key(EG(class_table), (Bucket *)delayed_early_binding, lcname) != NULL) { + Z_CE_P(delayed_early_binding) = ce; + return true; + } + } else { + /* If preloading is used, don't replace the existing bucket, add a new one. */ + if (zend_hash_add_ptr(EG(class_table), lcname, ce) != NULL) { + return true; + } } - Z_CE_P(delayed_early_binding) = ce; - return true; + zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name)); + return false; } return zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL; } diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index f9ed19080a609..0ad5d1c57199d 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -277,7 +277,7 @@ ZEND_API void destroy_zend_class(zval *zv) zend_class_entry *ce = Z_PTR_P(zv); zend_function *fn; - if (ce->ce_flags & (ZEND_ACC_IMMUTABLE|ZEND_ACC_PRELOADED)) { + if (ce->ce_flags & ZEND_ACC_IMMUTABLE) { return; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e820aef46cf17..696f663a82288 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7609,20 +7609,6 @@ ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT) if (UNEXPECTED(ce == NULL)) { zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1)); zv = zend_hash_find_known_hash(EG(class_table), rtd_key); - if (UNEXPECTED(zv == NULL)) { - SAVE_OPLINE(); - do { - ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED); - if (zend_preload_autoload - && zend_preload_autoload(EX(func)->op_array.filename) == SUCCESS) { - zv = zend_hash_find_known_hash(EG(class_table), rtd_key); - if (EXPECTED(zv != NULL)) { - break; - } - } - zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded"); - } while (0); - } ZEND_ASSERT(zv != NULL); ce = Z_CE_P(zv); if (!(ce->ce_flags & ZEND_ACC_LINKED)) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 92acc5e9b32db..afaff7ea8f4d9 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2937,20 +2937,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLE if (UNEXPECTED(ce == NULL)) { zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1)); zv = zend_hash_find_known_hash(EG(class_table), rtd_key); - if (UNEXPECTED(zv == NULL)) { - SAVE_OPLINE(); - do { - ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED); - if (zend_preload_autoload - && zend_preload_autoload(EX(func)->op_array.filename) == SUCCESS) { - zv = zend_hash_find_known_hash(EG(class_table), rtd_key); - if (EXPECTED(zv != NULL)) { - break; - } - } - zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded"); - } while (0); - } ZEND_ASSERT(zv != NULL); ce = Z_CE_P(zv); if (!(ce->ce_flags & ZEND_ACC_LINKED)) { diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 0f20905963511..86f14e3b20ca7 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3911,8 +3911,6 @@ static void preload_link(void) zend_string *key; bool found, changed; uint32_t i; - dtor_func_t orig_dtor; - zend_function *function; /* Resolve class dependencies */ do { @@ -4040,9 +4038,7 @@ static void preload_link(void) } ZEND_HASH_FOREACH_END(); } while (changed); - /* Move unlinked clases (and with unresolved constants) back to scripts */ - orig_dtor = EG(class_table)->pDestructor; - EG(class_table)->pDestructor = NULL; + /* Warn for classes that could not be linked. */ ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) { ce = Z_PTR_P(zv); if (ce->type == ZEND_INTERNAL_CLASS) { @@ -4064,25 +4060,8 @@ static void preload_link(void) ZSTR_VAL(ce->name), kind, name); } zend_string_release(key); - } 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) { @@ -4096,7 +4075,7 @@ static void preload_link(void) 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)) { + if (!zend_hash_exists(CG(class_table), key)) { MAKE_NOP(opline); } break; @@ -4414,8 +4393,6 @@ static zend_persistent_script* preload_script_in_shared_memory(zend_persistent_s return new_persistent_script; } -static zend_result preload_autoload(zend_string *filename); - static void preload_load(void) { /* Load into process tables */ @@ -4459,77 +4436,6 @@ static void preload_load(void) memset((void **) ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)) + old_map_ptr_last, 0, (CG(map_ptr_last) - old_map_ptr_last) * sizeof(void *)); } - - zend_preload_autoload = preload_autoload; -} - -static zend_result preload_autoload(zend_string *filename) -{ - zend_persistent_script *persistent_script; - zend_op_array *op_array; - zend_execute_data *old_execute_data; - zend_class_entry *old_fake_scope; - bool do_bailout = 0; - int ret = SUCCESS; - - if (zend_hash_exists(&EG(included_files), filename)) { - return FAILURE; - } - - persistent_script = zend_accel_hash_find(&ZCSG(hash), filename); - if (!persistent_script) { - return FAILURE; - } - - zend_hash_add_empty_element(&EG(included_files), filename); - - if (persistent_script->ping_auto_globals_mask & ~ZCG(auto_globals_mask)) { - zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask & ~ZCG(auto_globals_mask)); - } - - op_array = zend_accel_load_script(persistent_script, 1); - if (!op_array) { - return FAILURE; - } - - /* Execute in global context */ - old_execute_data = EG(current_execute_data); - EG(current_execute_data) = NULL; - old_fake_scope = EG(fake_scope); - EG(fake_scope) = NULL; - zend_exception_save(); - - zend_try { - zend_execute(op_array, NULL); - } zend_catch { - do_bailout = 1; - } zend_end_try(); - - if (EG(exception)) { - ret = FAILURE; - } - - zend_exception_restore(); - EG(fake_scope) = old_fake_scope; - EG(current_execute_data) = old_execute_data; - while (old_execute_data) { - if (old_execute_data->func && (ZEND_CALL_INFO(old_execute_data) & ZEND_CALL_HAS_SYMBOL_TABLE)) { - if (old_execute_data->symbol_table == &EG(symbol_table)) { - zend_attach_symbol_table(old_execute_data); - } - break; - } - old_execute_data = old_execute_data->prev_execute_data; - } - - destroy_op_array(op_array); - efree_size(op_array, sizeof(zend_op_array)); - - if (do_bailout) { - zend_bailout(); - } - - return ret; } static int accel_preload(const char *config, bool in_child)