]> granicus.if.org Git - php/commitdiff
Improve "instanceof". Interfaces of the left operand should be checked only if the...
authorDmitry Stogov <dmitry@zend.com>
Wed, 14 Jan 2015 12:06:26 +0000 (15:06 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 14 Jan 2015 12:06:26 +0000 (15:06 +0300)
Zend/zend_operators.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 7ce8664232dd48362581593ea399b7308cde73cc..e726f57b052e024194e134b21b2436abcf2c2ea0 100644 (file)
@@ -2004,31 +2004,69 @@ ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2) /*
 }
 /* }}} */
 
-ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only) /* {{{ */
+static zend_bool instanceof_inerface_only(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
 {
        uint32_t i;
 
-       for (i=0; i<instance_ce->num_interfaces; i++) {
-               if (instanceof_function(instance_ce->interfaces[i], ce)) {
+       for (i = 0; i < instance_ce->num_interfaces; i++) {
+               if (instanceof_inerface_only(instance_ce->interfaces[i], ce)) {
                        return 1;
                }
        }
-       if (!interfaces_only) {
-               while (instance_ce) {
-                       if (instance_ce == ce) {
+       return 0;
+}
+/* }}} */
+
+static zend_always_inline zend_bool instanceof_class(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
+{
+       while (instance_ce) {
+               if (instance_ce == ce) {
+                       return 1;
+               }
+               instance_ce = instance_ce->parent;
+       }
+       return 0;
+}
+/* }}} */
+
+static zend_bool instanceof_interface(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
+{
+       uint32_t i;
+
+       for (i = 0; i < instance_ce->num_interfaces; i++) {
+               if (instanceof_interface(instance_ce->interfaces[i], ce)) {
+                       return 1;
+               }
+       }
+       return instanceof_class(instance_ce, ce);
+}
+/* }}} */
+
+ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only) /* {{{ */
+{
+       if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+               if (!interfaces_only) {
+                       if (instanceof_inerface_only(instance_ce, ce)) {
                                return 1;
                        }
-                       instance_ce = instance_ce->parent;
+               } else {
+                       return instanceof_interface(instance_ce, ce);
                }
        }
-
+       if (!interfaces_only) {
+               return instanceof_class(instance_ce, ce);
+       }
        return 0;
 }
 /* }}} */
 
 ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
 {
-       return instanceof_function_ex(instance_ce, ce, 0);
+       if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+               return instanceof_interface(instance_ce, ce);
+       } else {
+               return instanceof_class(instance_ce, ce);
+       }
 }
 /* }}} */
 
index fb49a49faf79124ac29ae0e0393c1a21341e2733..6642eee7bb034b8f8969602efe34cd9af0b083ac 100644 (file)
@@ -3119,7 +3119,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
 #endif /* HAVE_DTRACE */
 
        if (ce != catch_ce) {
-               if (!instanceof_function(ce, catch_ce)) {
+               if (!catch_ce || !instanceof_function(ce, catch_ce)) {
                        if (opline->result.num) {
                                zend_throw_exception_internal(NULL);
                                HANDLE_EXCEPTION();
@@ -5597,7 +5597,7 @@ ZEND_VM_C_LABEL(try_instanceof):
                } else {
                        ce = Z_CE_P(EX_VAR(opline->op2.var));
                }
-               result = instanceof_function(Z_OBJCE_P(expr), ce);
+               result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
        } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
                expr = Z_REFVAL_P(expr);
                ZEND_VM_C_GOTO(try_instanceof);
index 8936f79e900aa12dcf3fda06fac76957052001dc..6f9d7456dcaa7a47edeb37e6baf6a0df2ed7eee8 100644 (file)
@@ -7248,7 +7248,7 @@ static int ZEND_FASTCALL  ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
 #endif /* HAVE_DTRACE */
 
        if (ce != catch_ce) {
-               if (!instanceof_function(ce, catch_ce)) {
+               if (!catch_ce || !instanceof_function(ce, catch_ce)) {
                        if (opline->result.num) {
                                zend_throw_exception_internal(NULL);
                                HANDLE_EXCEPTION();
@@ -26681,7 +26681,7 @@ try_instanceof:
                } else {
                        ce = Z_CE_P(EX_VAR(opline->op2.var));
                }
-               result = instanceof_function(Z_OBJCE_P(expr), ce);
+               result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
        } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
                expr = Z_REFVAL_P(expr);
                goto try_instanceof;
@@ -27599,7 +27599,7 @@ try_instanceof:
                } else {
                        ce = Z_CE_P(EX_VAR(opline->op2.var));
                }
-               result = instanceof_function(Z_OBJCE_P(expr), ce);
+               result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
        } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
                expr = Z_REFVAL_P(expr);
                goto try_instanceof;
@@ -34243,7 +34243,7 @@ try_instanceof:
                } else {
                        ce = Z_CE_P(EX_VAR(opline->op2.var));
                }
-               result = instanceof_function(Z_OBJCE_P(expr), ce);
+               result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
        } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
                expr = Z_REFVAL_P(expr);
                goto try_instanceof;
@@ -34649,7 +34649,7 @@ try_instanceof:
                } else {
                        ce = Z_CE_P(EX_VAR(opline->op2.var));
                }
-               result = instanceof_function(Z_OBJCE_P(expr), ce);
+               result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
        } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
                expr = Z_REFVAL_P(expr);
                goto try_instanceof;