From 9226695c221dc6e0a66ff03964f0bfae02477d69 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 17 Oct 2018 16:12:46 +0300 Subject: [PATCH 1/3] Mark "top-level" classes --- Zend/zend_compile.c | 4 ++++ Zend/zend_compile.h | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c907594fadb..39ee2a1063a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6322,6 +6322,10 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ CG(active_class_entry) = original_ce; + if (toplevel) { + ce->ce_flags |= ZEND_ACC_TOP_LEVEL; + } + if (toplevel /* We currently don't early-bind classes that implement interfaces or use traits */ && !(ce->ce_flags & (ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 4a597dd4676..acc0d9cf6f2 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -223,7 +223,7 @@ typedef struct _zend_oparray_context { /* Function has typed arguments / class has typed props | | | */ #define ZEND_ACC_HAS_TYPE_HINTS (1 << 8) /* ? | X | | */ /* | | | */ -/* Class Flags (unused: 15...) | | | */ +/* Class Flags (unused: 16...) | | | */ /* =========== | | | */ /* | | | */ /* Special class types | | | */ @@ -257,6 +257,9 @@ typedef struct _zend_oparray_context { /* User class has methods with static variables | | | */ #define ZEND_HAS_STATIC_IN_METHODS (1 << 14) /* X | | | */ /* | | | */ +/* Top-level class declaration | | | */ +#define ZEND_ACC_TOP_LEVEL (1 << 15) /* X | | | */ +/* | | | */ /* Function Flags (unused: 25...30) | | | */ /* ============== | | | */ /* | | | */ From 3575a2b8f921b2c7af9a725e54a1391243a71378 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 17 Oct 2018 16:55:52 +0300 Subject: [PATCH 2/3] Micro optimizations --- Zend/zend_interfaces.c | 66 ++++++++++++++++++++++++---------------- ext/spl/spl_array.c | 24 ++++++++------- ext/spl/spl_fixedarray.c | 24 ++++++++------- ext/spl/spl_iterators.c | 13 -------- 4 files changed, 66 insertions(+), 61 deletions(-) diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 2e7f70c7952..1fe5434504c 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -312,6 +312,7 @@ static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entr { uint32_t i; int t = -1; + zend_class_iterator_funcs *funcs_ptr; if (class_type->get_iterator) { if (class_type->type == ZEND_INTERNAL_CLASS) { @@ -340,16 +341,21 @@ static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entr } } class_type->get_iterator = zend_user_it_get_new_iterator; - if (class_type->iterator_funcs_ptr != NULL) { - class_type->iterator_funcs_ptr->zf_new_iterator = NULL; - } else if (class_type->type == ZEND_INTERNAL_CLASS) { - class_type->iterator_funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs)); - } else { - class_type->iterator_funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs)); - memset(class_type->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs)); - } + funcs_ptr = class_type->iterator_funcs_ptr; if (class_type->type == ZEND_INTERNAL_CLASS) { - class_type->iterator_funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&class_type->function_table, "getiterator", sizeof("getiterator") - 1); + if (!funcs_ptr) { + funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs)); + class_type->iterator_funcs_ptr = funcs_ptr; + } + funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&class_type->function_table, "getiterator", sizeof("getiterator") - 1); + } else { + if (!funcs_ptr) { + funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs)); + class_type->iterator_funcs_ptr = funcs_ptr; + memset(funcs_ptr, 0, sizeof(zend_class_iterator_funcs)); + } else { + funcs_ptr->zf_new_iterator = NULL; + } } return SUCCESS; } @@ -358,6 +364,8 @@ static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entr /* {{{ zend_implement_iterator */ static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry *class_type) { + zend_class_iterator_funcs *funcs_ptr; + if (class_type->get_iterator && class_type->get_iterator != zend_user_it_get_iterator) { if (class_type->type == ZEND_INTERNAL_CLASS) { /* inheritance ensures the class has the necessary userland methods */ @@ -374,24 +382,30 @@ static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry } } class_type->get_iterator = zend_user_it_get_iterator; - if (class_type->iterator_funcs_ptr != NULL) { - class_type->iterator_funcs_ptr->zf_valid = NULL; - class_type->iterator_funcs_ptr->zf_current = NULL; - class_type->iterator_funcs_ptr->zf_key = NULL; - class_type->iterator_funcs_ptr->zf_next = NULL; - class_type->iterator_funcs_ptr->zf_rewind = NULL; - } else if (class_type->type == ZEND_INTERNAL_CLASS) { - class_type->iterator_funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs)); - } else { - class_type->iterator_funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs)); - memset(class_type->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs)); - } + funcs_ptr = class_type->iterator_funcs_ptr; if (class_type->type == ZEND_INTERNAL_CLASS) { - class_type->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); - class_type->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); - class_type->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); - class_type->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); - class_type->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); + if (!funcs_ptr) { + funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs)); + class_type->iterator_funcs_ptr = funcs_ptr; + } else { + funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); + funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); + funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); + funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); + funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); + } + } else { + if (!funcs_ptr) { + funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs)); + class_type->iterator_funcs_ptr = funcs_ptr; + memset(funcs_ptr, 0, sizeof(zend_class_iterator_funcs)); + } else { + funcs_ptr->zf_valid = NULL; + funcs_ptr->zf_current = NULL; + funcs_ptr->zf_key = NULL; + funcs_ptr->zf_next = NULL; + funcs_ptr->zf_rewind = NULL; + } } return SUCCESS; } diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 04e73bf26e6..b341b8aa9e1 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -243,19 +243,21 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zval * /* Cache iterator functions if ArrayIterator or derived. Check current's */ /* cache since only current is always required */ if (intern->std.handlers == &spl_handler_ArrayIterator) { - if (!class_type->iterator_funcs_ptr->zf_current) { - class_type->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); - class_type->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); - class_type->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); - class_type->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); - class_type->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); + zend_class_iterator_funcs *funcs_ptr = class_type->iterator_funcs_ptr; + + if (!funcs_ptr->zf_current) { + funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); + funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); + funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); + funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); + funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); } if (inherited) { - if (class_type->iterator_funcs_ptr->zf_rewind->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_REWIND; - if (class_type->iterator_funcs_ptr->zf_valid->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_VALID; - if (class_type->iterator_funcs_ptr->zf_key->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_KEY; - if (class_type->iterator_funcs_ptr->zf_current->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_CURRENT; - if (class_type->iterator_funcs_ptr->zf_next->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_NEXT; + if (funcs_ptr->zf_rewind->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_REWIND; + if (funcs_ptr->zf_valid->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_VALID; + if (funcs_ptr->zf_key->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_KEY; + if (funcs_ptr->zf_current->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_CURRENT; + if (funcs_ptr->zf_next->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_NEXT; } } diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 392175f781f..5da70aa6a3a 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -207,6 +207,7 @@ static zend_object *spl_fixedarray_object_new_ex(zend_class_entry *class_type, z spl_fixedarray_object *intern; zend_class_entry *parent = class_type; int inherited = 0; + zend_class_iterator_funcs *funcs_ptr; intern = zend_object_alloc(sizeof(spl_fixedarray_object), parent); @@ -238,27 +239,28 @@ static zend_object *spl_fixedarray_object_new_ex(zend_class_entry *class_type, z php_error_docref(NULL, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplFixedArray"); } - if (!class_type->iterator_funcs_ptr->zf_current) { - class_type->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); - class_type->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); - class_type->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); - class_type->iterator_funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); - class_type->iterator_funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); + funcs_ptr = class_type->iterator_funcs_ptr; + if (!funcs_ptr->zf_current) { + funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); + funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); + funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); + funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); + funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); } if (inherited) { - if (class_type->iterator_funcs_ptr->zf_rewind->common.scope != parent) { + if (funcs_ptr->zf_rewind->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_REWIND; } - if (class_type->iterator_funcs_ptr->zf_valid->common.scope != parent) { + if (funcs_ptr->zf_valid->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_VALID; } - if (class_type->iterator_funcs_ptr->zf_key->common.scope != parent) { + if (funcs_ptr->zf_key->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_KEY; } - if (class_type->iterator_funcs_ptr->zf_current->common.scope != parent) { + if (funcs_ptr->zf_current->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_CURRENT; } - if (class_type->iterator_funcs_ptr->zf_next->common.scope != parent) { + if (funcs_ptr->zf_next->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_NEXT; } diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 40fa9f3f064..97a47d05c2d 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -1346,19 +1346,6 @@ static const zend_function_entry spl_funcs_RecursiveTreeIterator[] = { PHP_FE_END }; -#if MBO_0 -static int spl_dual_it_gets_implemented(zend_class_entry *interface, zend_class_entry *class_type) -{ - class_type->iterator_funcs_ptr->zf_valid = NULL; - class_type->iterator_funcs_ptr->zf_current = NULL; - class_type->iterator_funcs_ptr->zf_key = NULL; - class_type->iterator_funcs_ptr->zf_next = NULL; - class_type->iterator_funcs_ptr->zf_rewind = NULL; - - return SUCCESS; -} -#endif - static zend_function *spl_dual_it_get_method(zend_object **object, zend_string *method, const zval *key) { zend_function *function_handler; From b6ac50f9e6fec55f8e46f2443b2cf3e780374487 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 17 Oct 2018 16:56:32 +0300 Subject: [PATCH 3/3] Fixed comment --- Zend/zend_compile.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index acc0d9cf6f2..5ce27ba85f1 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -218,7 +218,7 @@ typedef struct _zend_oparray_context { /* | | | */ /* Immutable op_array and class_entries | | | */ /* (implemented only for lazy loading of op_arrays) | | | */ -#define ZEND_ACC_IMMUTABLE (1 << 7) /* ? | X | | */ +#define ZEND_ACC_IMMUTABLE (1 << 7) /* X | X | | */ /* | | | */ /* Function has typed arguments / class has typed props | | | */ #define ZEND_ACC_HAS_TYPE_HINTS (1 << 8) /* ? | X | | */