]> granicus.if.org Git - php/commitdiff
Reduce overhead of delayed early binding
authorDmitry Stogov <dmitry@zend.com>
Tue, 25 Jun 2019 11:20:41 +0000 (14:20 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 25 Jun 2019 11:20:41 +0000 (14:20 +0300)
Zend/zend_compile.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_handlers.h
Zend/zend_vm_opcodes.c

index 20501176487c21f192641f1d1a84e07abf0ea74b..1f20c4591ddf2bdc408abbf172841856d1915df7 100644 (file)
@@ -1150,12 +1150,26 @@ ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array, uint3
                while (opline_num != (uint32_t)-1) {
                        const zend_op *opline = &op_array->opcodes[opline_num];
                        zval *lcname = RT_CONSTANT(opline, opline->op1);
-                       zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname + 1));
-                       zend_string *lc_parent_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
-                       zend_class_entry *parent_ce = zend_lookup_class_ex(ce->parent_name, lc_parent_name, 0);
+                       zval *zv = zend_hash_find_ex(EG(class_table), Z_STR_P(lcname + 1), 1);
 
-                       if (ce && parent_ce && zend_can_early_bind(ce, parent_ce)) {
-                               do_bind_class(lcname, lc_parent_name);
+                       if (zv) {
+                               zend_class_entry *ce = Z_CE_P(zv);
+                               zend_string *lc_parent_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
+                               zend_class_entry *parent_ce = zend_hash_find_ex_ptr(EG(class_table), lc_parent_name, 1);
+
+                               if (parent_ce && zend_can_early_bind(ce, parent_ce)) {
+                                       zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
+                                       if (UNEXPECTED(!zv)) {
+                                               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));
+                                       } else {
+                                               ce->ce_flags |= ZEND_ACC_LINKED;
+                                               zend_do_inheritance(ce, parent_ce);
+                                               zend_build_properties_info_table(ce);
+                                               if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
+                                                       zend_verify_abstract_class(ce);
+                                               }
+                                       }
+                               }
                        }
                        opline_num = op_array->opcodes[opline_num].result.opline_num;
                }
index bd14092fb314cdd547b4ad62e9851b6944ad69ba..a5e888a1b429827a5d482e13d2886584a1ae66e4 100644 (file)
@@ -7034,16 +7034,23 @@ ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, CONST, ANY)
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
-ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, ANY)
+ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST)
 {
        USE_OPLINE
-       zval *zce, *orig_zce;
+       zval *lcname, *zv;
 
        SAVE_OPLINE();
-       if ((zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1)) == NULL ||
-           ((orig_zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)+1), 1)) != NULL &&
-            Z_CE_P(zce) != Z_CE_P(orig_zce))) {
-               do_bind_class(RT_CONSTANT(opline, opline->op1), (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
+       lcname = RT_CONSTANT(opline, opline->op1);
+       zv = zend_hash_find_ex(EG(class_table), Z_STR_P(lcname + 1), 1);
+
+       if (zv) {
+               zend_class_entry *ce = Z_CE_P(zv);
+               zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
+               if (UNEXPECTED(!zv)) {
+                       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));
+               } else {
+                       zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
+               }
        }
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
index 4f7aa5dc076338fea0adc791f5e0a2d95681d707..addf769b8a1b1d55e2d0b0ad412967a33f9f3029 100644 (file)
@@ -4026,20 +4026,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_SPEC_CONST_HANDL
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-       USE_OPLINE
-       zval *zce, *orig_zce;
-
-       SAVE_OPLINE();
-       if ((zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1)) == NULL ||
-           ((orig_zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)+1), 1)) != NULL &&
-            Z_CE_P(zce) != Z_CE_P(orig_zce))) {
-               do_bind_class(RT_CONSTANT(opline, opline->op1), (opline->op2_type == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
-       }
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
-}
-
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -6146,6 +6132,27 @@ array_key_exists_array:
 }
 
 /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zval *lcname, *zv;
+
+       SAVE_OPLINE();
+       lcname = RT_CONSTANT(opline, opline->op1);
+       zv = zend_hash_find_ex(EG(class_table), Z_STR_P(lcname + 1), 1);
+
+       if (zv) {
+               zend_class_entry *ce = Z_CE_P(zv);
+               zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
+               if (UNEXPECTED(!zv)) {
+                       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));
+               } else {
+                       zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
+               }
+       }
+       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -54098,7 +54105,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        (void*)&&ZEND_NULL_LABEL,
                        (void*)&&ZEND_YIELD_FROM_SPEC_CV_LABEL,
                        (void*)&&ZEND_DECLARE_CONST_SPEC_CONST_CONST_LABEL,
-                       (void*)&&ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_LABEL,
+                       (void*)&&ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_LABEL,
                        (void*)&&ZEND_NULL_LABEL,
                        (void*)&&ZEND_NULL_LABEL,
                        (void*)&&ZEND_NULL_LABEL,
@@ -56112,10 +56119,6 @@ zend_leave_helper_SPEC_LABEL:
                                VM_TRACE(ZEND_DECLARE_CLASS_SPEC_CONST)
                                ZEND_DECLARE_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
-                       HYBRID_CASE(ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST):
-                               VM_TRACE(ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST)
-                               ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-                               HYBRID_BREAK();
                        HYBRID_CASE(ZEND_YIELD_FROM_SPEC_CONST):
                                VM_TRACE(ZEND_YIELD_FROM_SPEC_CONST)
                                ZEND_YIELD_FROM_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -56340,6 +56343,10 @@ zend_leave_helper_SPEC_LABEL:
                                VM_TRACE(ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CONST)
                                ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST):
+                               VM_TRACE(ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST)
+                               ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
                        HYBRID_CASE(ZEND_DECLARE_CONST_SPEC_CONST_CONST):
                                VM_TRACE(ZEND_DECLARE_CONST_SPEC_CONST_CONST)
                                ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -63807,7 +63814,7 @@ void zend_vm_init(void)
                ZEND_NULL_HANDLER,
                ZEND_YIELD_FROM_SPEC_CV_HANDLER,
                ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER,
-               ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_HANDLER,
+               ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER,
                ZEND_NULL_HANDLER,
                ZEND_NULL_HANDLER,
                ZEND_NULL_HANDLER,
index a8aae733fd870dce3c403976e101110a81a29609..12f03bf49ef61321bc70d445eb88813a9ac70dfc 100644 (file)
        _(2703, ZEND_YIELD_FROM_SPEC_VAR) \
        _(2705, ZEND_YIELD_FROM_SPEC_CV) \
        _(2706, ZEND_DECLARE_CONST_SPEC_CONST_CONST) \
-       _(2707, ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST) \
+       _(2707, ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST) \
        _(2758, ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST) \
        _(2759, ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP) \
        _(2760, ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR) \
index 70d9fbcc194250c32f58fab782e30ddb81a83d41..38654cf2ce4b601b79ff229b53e73f95222c1c6e 100644 (file)
@@ -380,7 +380,7 @@ static uint32_t zend_vm_opcodes_flags[209] = {
        0x00000003,
        0x00000303,
        0x00000000,
-       0x00000003,
+       0x00000303,
        0x00000000,
        0x00006701,
        0x00060757,