diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-10-25 10:45:42 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-10-25 10:51:17 +0200 |
commit | c858d17f06179aa25f6e8aa06965313fd519d8e9 (patch) | |
tree | de199c2dada0099a344ff595cf024958f98caa5b | |
parent | bd7b1afd6eb623a4905673dfc92bb0de62f23edd (diff) | |
download | php-git-c858d17f06179aa25f6e8aa06965313fd519d8e9.tar.gz |
Optimize instanceof_function
Split out the simple equality check into an inline function --
this is one of the common cases.
Replace instanceof_function_ex with zend_class_implements_interface.
There are a few more places where it may be used.
-rw-r--r-- | Zend/zend_API.c | 4 | ||||
-rw-r--r-- | Zend/zend_interfaces.c | 2 | ||||
-rw-r--r-- | Zend/zend_object_handlers.c | 8 | ||||
-rw-r--r-- | Zend/zend_operators.c | 64 | ||||
-rw-r--r-- | Zend/zend_operators.h | 9 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 2 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 6 | ||||
-rw-r--r-- | ext/intl/dateformat/dateformat_helpers.cpp | 3 | ||||
-rw-r--r-- | ext/opcache/zend_persist.c | 4 |
9 files changed, 51 insertions, 51 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index b32c82a1b9..9bc6b12cd6 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -4282,7 +4282,7 @@ ZEND_API zend_bool zend_is_iterable(zval *iterable) /* {{{ */ case IS_ARRAY: return 1; case IS_OBJECT: - return instanceof_function(Z_OBJCE_P(iterable), zend_ce_traversable); + return zend_class_implements_interface(Z_OBJCE_P(iterable), zend_ce_traversable); default: return 0; } @@ -4299,7 +4299,7 @@ ZEND_API zend_bool zend_is_countable(zval *countable) /* {{{ */ return 1; } - return instanceof_function(Z_OBJCE_P(countable), zend_ce_countable); + return zend_class_implements_interface(Z_OBJCE_P(countable), zend_ce_countable); default: return 0; } diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 5d58b3e178..d2b96e6bf3 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -512,7 +512,7 @@ static int zend_implement_serializable(zend_class_entry *interface, zend_class_e { if (class_type->parent && (class_type->parent->serialize || class_type->parent->unserialize) - && !instanceof_function_ex(class_type->parent, zend_ce_serializable, 1)) { + && !zend_class_implements_interface(class_type->parent, zend_ce_serializable)) { return FAILURE; } if (!class_type->serialize) { diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 3df9160180..c5fd87eb97 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -898,7 +898,7 @@ ZEND_API zval *zend_std_read_dimension(zend_object *object, zval *offset, int ty zend_class_entry *ce = object->ce; zval tmp_offset; - if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { + if (EXPECTED(zend_class_implements_interface(ce, zend_ce_arrayaccess) != 0)) { if (offset == NULL) { /* [] construct */ ZVAL_NULL(&tmp_offset); @@ -947,7 +947,7 @@ ZEND_API void zend_std_write_dimension(zend_object *object, zval *offset, zval * zend_class_entry *ce = object->ce; zval tmp_offset; - if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { + if (EXPECTED(zend_class_implements_interface(ce, zend_ce_arrayaccess) != 0)) { if (!offset) { ZVAL_NULL(&tmp_offset); } else { @@ -969,7 +969,7 @@ ZEND_API int zend_std_has_dimension(zend_object *object, zval *offset, int check zval retval, tmp_offset; int result; - if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { + if (EXPECTED(zend_class_implements_interface(ce, zend_ce_arrayaccess) != 0)) { ZVAL_COPY_DEREF(&tmp_offset, offset); GC_ADDREF(object); zend_call_method_with_1_params(object, ce, NULL, "offsetexists", &retval, &tmp_offset); @@ -1112,7 +1112,7 @@ ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset) /* {{{ zend_class_entry *ce = object->ce; zval tmp_offset; - if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1)) { + if (zend_class_implements_interface(ce, zend_ce_arrayaccess)) { ZVAL_COPY_DEREF(&tmp_offset, offset); GC_ADDREF(object); zend_call_method_with_1_params(object, ce, NULL, "offsetunset", NULL, &tmp_offset); diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index ac11ed6668..69ee522b4c 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2175,53 +2175,49 @@ ZEND_API int ZEND_FASTCALL is_smaller_or_equal_function(zval *result, zval *op1, } /* }}} */ -static zend_always_inline zend_bool instanceof_class(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */ -{ - do { - if (instance_ce == ce) { - return 1; - } - instance_ce = instance_ce->parent; - } while (instance_ce); - return 0; -} -/* }}} */ - -static zend_bool ZEND_FASTCALL instanceof_interface(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */ +ZEND_API zend_bool ZEND_FASTCALL zend_class_implements_interface(const zend_class_entry *class_ce, const zend_class_entry *interface_ce) /* {{{ */ { uint32_t i; + ZEND_ASSERT(!(class_ce->ce_flags & ZEND_ACC_INTERFACE)); + ZEND_ASSERT(interface_ce->ce_flags & ZEND_ACC_INTERFACE); - if (instance_ce->num_interfaces) { - ZEND_ASSERT(instance_ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES); - for (i = 0; i < instance_ce->num_interfaces; i++) { - if (instance_ce->interfaces[i] == ce) { + if (class_ce->num_interfaces) { + ZEND_ASSERT(class_ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES); + for (i = 0; i < class_ce->num_interfaces; i++) { + if (class_ce->interfaces[i] == interface_ce) { return 1; } } } - return instance_ce == ce; -} -/* }}} */ - -// TODO: It would make more sense to expose instanceof_class + instanceof_interface instead -ZEND_API zend_bool ZEND_FASTCALL instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool is_interface) /* {{{ */ -{ - if (is_interface) { - ZEND_ASSERT(ce->ce_flags & ZEND_ACC_INTERFACE); - return instanceof_interface(instance_ce, ce); - } else { - ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_INTERFACE)); - return instanceof_class(instance_ce, ce); - } + return 0; } /* }}} */ -ZEND_API zend_bool ZEND_FASTCALL instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */ +ZEND_API zend_bool ZEND_FASTCALL instanceof_function_slow(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */ { + ZEND_ASSERT(instance_ce != ce && "Should have been checked already"); if (ce->ce_flags & ZEND_ACC_INTERFACE) { - return instanceof_interface(instance_ce, ce); + uint32_t i; + + if (instance_ce->num_interfaces) { + ZEND_ASSERT(instance_ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES); + for (i = 0; i < instance_ce->num_interfaces; i++) { + if (instance_ce->interfaces[i] == ce) { + return 1; + } + } + } + return 0; } else { - return instanceof_class(instance_ce, ce); + while (1) { + instance_ce = instance_ce->parent; + if (instance_ce == ce) { + return 1; + } + if (instance_ce == NULL) { + return 0; + } + } } } /* }}} */ diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 8ae6fe664b..ee7c951c7d 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -63,8 +63,13 @@ ZEND_API int ZEND_FASTCALL is_not_equal_function(zval *result, zval *op1, zval * ZEND_API int ZEND_FASTCALL is_smaller_function(zval *result, zval *op1, zval *op2); ZEND_API int ZEND_FASTCALL is_smaller_or_equal_function(zval *result, zval *op1, zval *op2); -ZEND_API zend_bool ZEND_FASTCALL instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool is_interface); -ZEND_API zend_bool ZEND_FASTCALL instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce); +ZEND_API zend_bool ZEND_FASTCALL zend_class_implements_interface(const zend_class_entry *class_ce, const zend_class_entry *interface_ce); +ZEND_API zend_bool ZEND_FASTCALL instanceof_function_slow(const zend_class_entry *instance_ce, const zend_class_entry *ce); + +static zend_always_inline zend_bool instanceof_function( + const zend_class_entry *instance_ce, const zend_class_entry *ce) { + return instance_ce == ce || instanceof_function_slow(instance_ce, ce); +} /** * Checks whether the string "str" with length "length" is numeric. The value diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 6d14873360..9797cfe649 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8424,7 +8424,7 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED) } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(zobj->ce, zend_ce_countable)) { + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { zval retval; zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index bf643d3fbd..27c22ebc12 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -9254,7 +9254,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_ } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(zobj->ce, zend_ce_countable)) { + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { zval retval; zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); @@ -16319,7 +16319,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDL } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(zobj->ce, zend_ce_countable)) { + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { zval retval; zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); @@ -45446,7 +45446,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(zobj->ce, zend_ce_countable)) { + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { zval retval; zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); diff --git a/ext/intl/dateformat/dateformat_helpers.cpp b/ext/intl/dateformat/dateformat_helpers.cpp index f58317ebc1..f578512de6 100644 --- a/ext/intl/dateformat/dateformat_helpers.cpp +++ b/ext/intl/dateformat/dateformat_helpers.cpp @@ -69,8 +69,7 @@ int datefmt_process_calendar_arg(zval* calendar_zv, cal_int_type = Z_LVAL_P(calendar_zv); } else if (Z_TYPE_P(calendar_zv) == IS_OBJECT && - instanceof_function_ex(Z_OBJCE_P(calendar_zv), - Calendar_ce_ptr, 0)) { + instanceof_function(Z_OBJCE_P(calendar_zv), Calendar_ce_ptr)) { cal = calendar_fetch_native_calendar(calendar_zv); if (cal == NULL) { diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index a2fb94d7f6..60c7620ee9 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -923,10 +923,10 @@ static void zend_update_parent_ce(zend_class_entry *ce) if (ce->iterator_funcs_ptr) { memset(ce->iterator_funcs_ptr, 0, sizeof(zend_class_iterator_funcs)); - if (instanceof_function_ex(ce, zend_ce_aggregate, 1)) { + if (zend_class_implements_interface(ce, zend_ce_aggregate)) { ce->iterator_funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&ce->function_table, "getiterator", sizeof("getiterator") - 1); } - if (instanceof_function_ex(ce, zend_ce_iterator, 1)) { + if (zend_class_implements_interface(ce, zend_ce_iterator)) { ce->iterator_funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&ce->function_table, "rewind", sizeof("rewind") - 1); ce->iterator_funcs_ptr->zf_valid = zend_hash_str_find_ptr(&ce->function_table, "valid", sizeof("valid") - 1); ce->iterator_funcs_ptr->zf_key = zend_hash_str_find_ptr(&ce->function_table, "key", sizeof("key") - 1); |