summaryrefslogtreecommitdiff
path: root/Zend/zend_execute_API.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_execute_API.c')
-rw-r--r--Zend/zend_execute_API.c335
1 files changed, 162 insertions, 173 deletions
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 6eb9dfacee..e1001062e5 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
+ | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -33,6 +33,8 @@
#include "zend_generators.h"
#include "zend_vm.h"
#include "zend_float.h"
+#include "zend_weakrefs.h"
+#include "zend_inheritance.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
@@ -130,8 +132,8 @@ void init_executor(void) /* {{{ */
original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv);
#endif
- EG(symtable_cache_ptr) = EG(symtable_cache) - 1;
- EG(symtable_cache_limit) = EG(symtable_cache) + SYMTABLE_CACHE_SIZE - 1;
+ EG(symtable_cache_ptr) = EG(symtable_cache);
+ EG(symtable_cache_limit) = EG(symtable_cache) + SYMTABLE_CACHE_SIZE;
EG(no_extensions) = 0;
EG(function_table) = CG(function_table);
@@ -183,6 +185,8 @@ void init_executor(void) /* {{{ */
EG(persistent_functions_count) = EG(function_table)->nNumUsed;
EG(persistent_classes_count) = EG(class_table)->nNumUsed;
+ zend_weakrefs_init();
+
EG(active) = 1;
}
/* }}} */
@@ -205,11 +209,11 @@ static void zend_unclean_zval_ptr_dtor(zval *zv) /* {{{ */
if (Z_TYPE_P(zv) == IS_INDIRECT) {
zv = Z_INDIRECT_P(zv);
}
- i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC);
+ i_zval_ptr_dtor(zv);
}
/* }}} */
-static void zend_throw_or_error(int fetch_type, zend_class_entry *exception_ce, const char *format, ...) /* {{{ */
+static ZEND_COLD void zend_throw_or_error(int fetch_type, zend_class_entry *exception_ce, const char *format, ...) /* {{{ */
{
va_list va;
char *message = NULL;
@@ -261,41 +265,57 @@ void shutdown_executor(void) /* {{{ */
zend_llist_destroy(&CG(open_files));
} zend_end_try();
+ EG(flags) |= EG_FLAGS_IN_RESOURCE_SHUTDOWN;
zend_try {
zend_close_rsrc_list(&EG(regular_list));
} zend_end_try();
- zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown);
-
- /* All resources and objects are destroyed. */
- /* No PHP callback functions may be called after this point. */
+ /* No PHP callback functions should be called after this point. */
EG(active) = 0;
- zend_try {
- zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator);
- } zend_end_try();
-
- if (fast_shutdown) {
- /* Fast Request Shutdown
- * =====================
- * Zend Memory Manager frees memory by its own. We don't have to free
- * each allocated block separately.
- */
- zend_hash_discard(EG(zend_constants), EG(persistent_constants_count));
- zend_hash_discard(EG(function_table), EG(persistent_functions_count));
- zend_hash_discard(EG(class_table), EG(persistent_classes_count));
- zend_cleanup_internal_classes();
- } else {
+ if (!fast_shutdown) {
zend_hash_graceful_reverse_destroy(&EG(symbol_table));
-#if ZEND_DEBUG
- if (gc_enabled() && !CG(unclean_shutdown)) {
- gc_collect_cycles();
- }
-#endif
+ /* Release static properties and static variables prior to the final GC run,
+ * as they may hold GC roots. */
+ 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;
+ }
+ 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_REVERSE_FOREACH_VAL(EG(class_table), zv) {
+ zend_class_entry *ce = Z_PTR_P(zv);
+ 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) {
+ if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) == 0) {
+ zend_array_destroy(ht);
+ }
+ ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
+ }
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+ } ZEND_HASH_FOREACH_END();
- /* remove error handlers before destroying classes and functions,
- * so that if handler used some class, crash would not happen */
+ /* Also release error and exception handlers, which may hold objects. */
if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
zval_ptr_dtor(&EG(user_error_handler));
ZVAL_UNDEF(&EG(user_error_handler));
@@ -310,6 +330,32 @@ void shutdown_executor(void) /* {{{ */
zend_stack_clean(&EG(user_error_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
+#if ZEND_DEBUG
+ if (gc_enabled() && !CG(unclean_shutdown)) {
+ gc_collect_cycles();
+ }
+#endif
+ }
+
+ zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown);
+
+ zend_weakrefs_shutdown();
+
+ zend_try {
+ zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator);
+ } zend_end_try();
+
+ if (fast_shutdown) {
+ /* Fast Request Shutdown
+ * =====================
+ * Zend Memory Manager frees memory by its own. We don't have to free
+ * each allocated block separately.
+ */
+ zend_hash_discard(EG(zend_constants), EG(persistent_constants_count));
+ zend_hash_discard(EG(function_table), EG(persistent_functions_count));
+ zend_hash_discard(EG(class_table), EG(persistent_classes_count));
+ zend_cleanup_internal_classes();
+ } else {
zend_vm_stack_destroy();
if (EG(full_tables_cleanup)) {
@@ -319,7 +365,7 @@ void shutdown_executor(void) /* {{{ */
} else {
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) {
+ if (_idx == EG(persistent_constants_count)) {
break;
}
zval_ptr_dtor_nogc(&c->value);
@@ -329,17 +375,18 @@ void shutdown_executor(void) /* {{{ */
efree(c);
zend_string_release_ex(key, 0);
} ZEND_HASH_FOREACH_END_DEL();
+
ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(function_table), key, zv) {
zend_function *func = Z_PTR_P(zv);
- if (func->type == ZEND_INTERNAL_FUNCTION) {
+ if (_idx == EG(persistent_functions_count)) {
break;
}
destroy_op_array(&func->op_array);
zend_string_release_ex(key, 0);
} ZEND_HASH_FOREACH_END_DEL();
+
ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
- zend_class_entry *ce = Z_PTR_P(zv);
- if (ce->type == ZEND_INTERNAL_CLASS) {
+ if (_idx == EG(persistent_classes_count)) {
break;
}
destroy_zend_class(zv);
@@ -347,12 +394,10 @@ void shutdown_executor(void) /* {{{ */
} ZEND_HASH_FOREACH_END_DEL();
}
- zend_cleanup_internal_classes();
-
- while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
+ while (EG(symtable_cache_ptr) > EG(symtable_cache)) {
+ EG(symtable_cache_ptr)--;
zend_hash_destroy(*EG(symtable_cache_ptr));
FREE_HASHTABLE(*EG(symtable_cache_ptr));
- EG(symtable_cache_ptr)--;
}
zend_hash_destroy(&EG(included_files));
@@ -514,7 +559,7 @@ ZEND_API zend_bool zend_is_executing(void) /* {{{ */
}
/* }}} */
-ZEND_API int zend_use_undefined_constant(zend_string *name, zend_ast_attr attr, zval *result) /* {{{ */
+ZEND_API ZEND_COLD int zend_use_undefined_constant(zend_string *name, zend_ast_attr attr, zval *result) /* {{{ */
{
char *colon;
@@ -605,6 +650,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
zend_execute_data *call, dummy_execute_data;
zend_fcall_info_cache fci_cache_local;
zend_function *func;
+ uint32_t call_info;
+ void *object_or_called_scope;
ZVAL_UNDEF(fci->retval);
@@ -677,11 +724,18 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
}
func = fci_cache->function_handler;
- fci->object = (func->common.fn_flags & ZEND_ACC_STATIC) ?
- NULL : fci_cache->object;
+ if ((func->common.fn_flags & ZEND_ACC_STATIC) || !fci_cache->object) {
+ fci->object = NULL;
+ object_or_called_scope = fci_cache->called_scope;
+ call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC;
+ } else {
+ fci->object = fci_cache->object;
+ object_or_called_scope = fci->object;
+ call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC | ZEND_CALL_HAS_THIS;
+ }
- call = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC,
- func, fci->param_count, fci_cache->called_scope, fci->object);
+ call = zend_vm_stack_push_call_frame(call_info,
+ func, fci->param_count, object_or_called_scope);
if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_DEPRECATED)) {
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
@@ -692,6 +746,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
zend_vm_stack_free_call_frame(call);
if (EG(current_execute_data) == &dummy_execute_data) {
EG(current_execute_data) = dummy_execute_data.prev_execute_data;
+ zend_rethrow_exception(EG(current_execute_data));
}
return FAILURE;
}
@@ -763,7 +818,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
ZVAL_NULL(fci->retval);
call->prev_execute_data = EG(current_execute_data);
- call->return_value = NULL; /* this is not a constructor call */
EG(current_execute_data) = call;
if (EXPECTED(zend_execute_internal == NULL)) {
/* saves one function call if zend_execute_internal is not used */
@@ -828,7 +882,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
}
/* }}} */
-ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload) /* {{{ */
+ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *key, uint32_t flags) /* {{{ */
{
zend_class_entry *ce = NULL;
zval args[1], *zv;
@@ -839,7 +893,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
zend_class_entry *orig_fake_scope;
if (key) {
- lc_name = Z_STR_P(key);
+ lc_name = key;
} else {
if (name == NULL || !ZSTR_LEN(name)) {
return NULL;
@@ -858,13 +912,23 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
if (!key) {
zend_string_release_ex(lc_name, 0);
}
- return (zend_class_entry*)Z_PTR_P(zv);
+ ce = (zend_class_entry*)Z_PTR_P(zv);
+ if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_LINKED))) {
+ if ((flags & ZEND_FETCH_CLASS_ALLOW_UNLINKED) ||
+ ((flags & ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED) &&
+ (ce->ce_flags & ZEND_ACC_NEARLY_LINKED))) {
+ ce->ce_flags |= ZEND_ACC_HAS_UNLINKED_USES;
+ return ce;
+ }
+ return NULL;
+ }
+ return ce;
}
/* The compiler is not-reentrant. Make sure we __autoload() only during run-time
* (doesn't impact functionality of __autoload()
*/
- if (!use_autoload || zend_is_compiling()) {
+ if ((flags & ZEND_FETCH_CLASS_NO_AUTOLOAD) || zend_is_compiling()) {
if (!key) {
zend_string_release_ex(lc_name, 0);
}
@@ -948,7 +1012,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */
{
- return zend_lookup_class_ex(name, NULL, 1);
+ return zend_lookup_class_ex(name, NULL, 0);
}
/* }}} */
@@ -1077,7 +1141,7 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name,
static void zend_set_timeout_ex(zend_long seconds, int reset_signals);
-ZEND_API ZEND_NORETURN void zend_timeout(int dummy) /* {{{ */
+ZEND_API ZEND_NORETURN void ZEND_FASTCALL zend_timeout(int dummy) /* {{{ */
{
#if defined(PHP_WIN32)
# ifndef ZTS
@@ -1130,7 +1194,7 @@ static void zend_timeout_handler(int dummy) /* {{{ */
output_len = snprintf(log_buffer, sizeof(log_buffer), "\nFatal error: Maximum execution time of " ZEND_LONG_FMT "+" ZEND_LONG_FMT " seconds exceeded (terminated) in %s on line %d\n", EG(timeout_seconds), EG(hard_timeout), error_filename, error_lineno);
if (output_len > 0) {
- write(2, log_buffer, MIN(output_len, sizeof(log_buffer)));
+ zend_quiet_write(2, log_buffer, MIN(output_len, sizeof(log_buffer)));
}
_exit(124);
}
@@ -1197,7 +1261,7 @@ static void zend_set_timeout_ex(zend_long seconds, int reset_signals) /* {{{ */
timer, so we could end up with just an ignored timeout. Instead
delete and recreate. */
if (NULL != tq_timer) {
- if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
+ if (!DeleteTimerQueueTimer(NULL, tq_timer, INVALID_HANDLE_VALUE)) {
tq_timer = NULL;
zend_error_noreturn(E_ERROR, "Could not delete queued timer");
return;
@@ -1212,8 +1276,7 @@ static void zend_set_timeout_ex(zend_long seconds, int reset_signals) /* {{{ */
zend_error_noreturn(E_ERROR, "Could not queue new timer");
return;
}
-#else
-# ifdef HAVE_SETITIMER
+#elif defined(HAVE_SETITIMER)
{
struct itimerval t_r; /* timeout requested */
int signo;
@@ -1222,39 +1285,38 @@ static void zend_set_timeout_ex(zend_long seconds, int reset_signals) /* {{{ */
t_r.it_value.tv_sec = seconds;
t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;
-# ifdef __CYGWIN__
+# ifdef __CYGWIN__
setitimer(ITIMER_REAL, &t_r, NULL);
}
signo = SIGALRM;
-# else
+# else
setitimer(ITIMER_PROF, &t_r, NULL);
}
signo = SIGPROF;
-# endif
+# endif
if (reset_signals) {
-# ifdef ZEND_SIGNALS
+# ifdef ZEND_SIGNALS
zend_signal(signo, zend_timeout_handler);
-# else
+# else
sigset_t sigset;
-# ifdef HAVE_SIGACTION
+# ifdef HAVE_SIGACTION
struct sigaction act;
act.sa_handler = zend_timeout_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESETHAND | SA_NODEFER;
sigaction(signo, &act, NULL);
-# else
+# else
signal(signo, zend_timeout_handler);
-# endif /* HAVE_SIGACTION */
+# endif /* HAVE_SIGACTION */
sigemptyset(&sigset);
sigaddset(&sigset, signo);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
-# endif /* ZEND_SIGNALS */
+# endif /* ZEND_SIGNALS */
}
}
-# endif /* HAVE_SETITIMER */
-#endif
+#endif /* HAVE_SETITIMER */
}
/* }}} */
@@ -1271,7 +1333,7 @@ void zend_unset_timeout(void) /* {{{ */
{
#ifdef ZEND_WIN32
if (NULL != tq_timer) {
- if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
+ if (!DeleteTimerQueueTimer(NULL, tq_timer, INVALID_HANDLE_VALUE)) {
EG(timed_out) = 0;
tq_timer = NULL;
zend_error_noreturn(E_ERROR, "Could not delete queued timer");
@@ -1279,23 +1341,20 @@ void zend_unset_timeout(void) /* {{{ */
}
tq_timer = NULL;
}
- EG(timed_out) = 0;
-#else
-# ifdef HAVE_SETITIMER
+#elif defined(HAVE_SETITIMER)
if (EG(timeout_seconds)) {
struct itimerval no_timeout;
no_timeout.it_value.tv_sec = no_timeout.it_value.tv_usec = no_timeout.it_interval.tv_sec = no_timeout.it_interval.tv_usec = 0;
-#ifdef __CYGWIN__
+# ifdef __CYGWIN__
setitimer(ITIMER_REAL, &no_timeout, NULL);
-#else
+# else
setitimer(ITIMER_PROF, &no_timeout, NULL);
-#endif
+# endif
}
-# endif
- EG(timed_out) = 0;
#endif
+ EG(timed_out) = 0;
}
/* }}} */
@@ -1339,8 +1398,8 @@ check_fetch_type:
}
if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
- return zend_lookup_class_ex(class_name, NULL, 0);
- } else if ((ce = zend_lookup_class_ex(class_name, NULL, 1)) == NULL) {
+ return zend_lookup_class_ex(class_name, NULL, fetch_type);
+ } else if ((ce = zend_lookup_class_ex(class_name, NULL, fetch_type)) == NULL) {
if (!(fetch_type & ZEND_FETCH_CLASS_SILENT) && !EG(exception)) {
if (fetch_sub_type == ZEND_FETCH_CLASS_INTERFACE) {
zend_throw_or_error(fetch_type, NULL, "Interface '%s' not found", ZSTR_VAL(class_name));
@@ -1356,84 +1415,39 @@ check_fetch_type:
}
/* }}} */
-zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, const zval *key, int fetch_type) /* {{{ */
+zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *key, int fetch_type) /* {{{ */
{
zend_class_entry *ce;
if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
- return zend_lookup_class_ex(class_name, key, 0);
- } else if ((ce = zend_lookup_class_ex(class_name, key, 1)) == NULL) {
- if ((fetch_type & ZEND_FETCH_CLASS_SILENT) == 0 && !EG(exception)) {
- if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) {
- zend_throw_or_error(fetch_type, NULL, "Interface '%s' not found", ZSTR_VAL(class_name));
- } else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) {
- zend_throw_or_error(fetch_type, NULL, "Trait '%s' not found", ZSTR_VAL(class_name));
- } else {
- zend_throw_or_error(fetch_type, NULL, "Class '%s' not found", ZSTR_VAL(class_name));
- }
- }
- return NULL;
- }
- return ce;
-}
-/* }}} */
-
-#define MAX_ABSTRACT_INFO_CNT 3
-#define MAX_ABSTRACT_INFO_FMT "%s%s%s%s"
-#define DISPLAY_ABSTRACT_FN(idx) \
- ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \
- ai.afn[idx] ? "::" : "", \
- ai.afn[idx] ? ZSTR_VAL(ai.afn[idx]->common.function_name) : "", \
- ai.afn[idx] && ai.afn[idx + 1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "")
-
-typedef struct _zend_abstract_info {
- zend_function *afn[MAX_ABSTRACT_INFO_CNT + 1];
- int cnt;
- int ctor;
-} zend_abstract_info;
-
-static void zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai) /* {{{ */
-{
- if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
- if (ai->cnt < MAX_ABSTRACT_INFO_CNT) {
- ai->afn[ai->cnt] = fn;
+ return zend_lookup_class_ex(class_name, key, fetch_type);
+ } else if ((ce = zend_lookup_class_ex(class_name, key, fetch_type)) == NULL) {
+ if (fetch_type & ZEND_FETCH_CLASS_SILENT) {
+ return NULL;
}
- if (fn->common.fn_flags & ZEND_ACC_CTOR) {
- if (!ai->ctor) {
- ai->cnt++;
- ai->ctor = 1;
- } else {
- ai->afn[ai->cnt] = NULL;
+ if (EG(exception)) {
+ if (!(fetch_type & ZEND_FETCH_CLASS_EXCEPTION)) {
+ zend_string *exception_str;
+ zval exception_zv;
+ ZVAL_OBJ(&exception_zv, EG(exception));
+ Z_ADDREF(exception_zv);
+ zend_clear_exception();
+ exception_str = zval_get_string(&exception_zv);
+ zend_error_noreturn(E_ERROR,
+ "During class fetch: Uncaught %s", ZSTR_VAL(exception_str));
}
- } else {
- ai->cnt++;
+ return NULL;
}
- }
-}
-/* }}} */
-
-void zend_verify_abstract_class(zend_class_entry *ce) /* {{{ */
-{
- zend_function *func;
- zend_abstract_info ai;
-
- if ((ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) && !(ce->ce_flags & (ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
- memset(&ai, 0, sizeof(ai));
-
- ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
- zend_verify_abstract_class_function(func, &ai);
- } ZEND_HASH_FOREACH_END();
-
- if (ai.cnt) {
- zend_error_noreturn(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")",
- ZSTR_VAL(ce->name), ai.cnt,
- ai.cnt > 1 ? "s" : "",
- DISPLAY_ABSTRACT_FN(0),
- DISPLAY_ABSTRACT_FN(1),
- DISPLAY_ABSTRACT_FN(2)
- );
+ if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) {
+ zend_throw_or_error(fetch_type, NULL, "Interface '%s' not found", ZSTR_VAL(class_name));
+ } else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) {
+ zend_throw_or_error(fetch_type, NULL, "Trait '%s' not found", ZSTR_VAL(class_name));
+ } else {
+ zend_throw_or_error(fetch_type, NULL, "Class '%s' not found", ZSTR_VAL(class_name));
}
+ return NULL;
}
+ return ce;
}
/* }}} */
@@ -1461,9 +1475,8 @@ ZEND_API zend_array *zend_rebuild_symbol_table(void) /* {{{ */
}
ZEND_ADD_CALL_FLAG(ex, ZEND_CALL_HAS_SYMBOL_TABLE);
- if (EG(symtable_cache_ptr) >= EG(symtable_cache)) {
- /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
- symbol_table = ex->symbol_table = *(EG(symtable_cache_ptr)--);
+ if (EG(symtable_cache_ptr) > EG(symtable_cache)) {
+ symbol_table = ex->symbol_table = *(--EG(symtable_cache_ptr));
if (!ex->func->op_array.last_var) {
return symbol_table;
}
@@ -1637,27 +1650,3 @@ ZEND_API int zend_set_local_var_str(const char *name, size_t len, zval *value, i
return FAILURE;
}
/* }}} */
-
-ZEND_API int zend_forbid_dynamic_call(const char *func_name) /* {{{ */
-{
- zend_execute_data *ex = EG(current_execute_data);
- ZEND_ASSERT(ex != NULL && ex->func != NULL);
-
- if (ZEND_CALL_INFO(ex) & ZEND_CALL_DYNAMIC) {
- zend_error(E_WARNING, "Cannot call %s dynamically", func_name);
- return FAILURE;
- }
-
- return SUCCESS;
-}
-/* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * indent-tabs-mode: t
- * End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
- */