]> granicus.if.org Git - php/commitdiff
Embed FETCH_CLASS <string> into the following NEW
authorDmitry Stogov <dmitry@zend.com>
Thu, 23 Oct 2014 07:52:34 +0000 (11:52 +0400)
committerDmitry Stogov <dmitry@zend.com>
Thu, 23 Oct 2014 07:52:34 +0000 (11:52 +0400)
Zend/zend_compile.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/opcache/Optimizer/compact_literals.c
ext/opcache/Optimizer/zend_optimizer.c
ext/spl/php_spl.c

index 988a42b496ddd6c10a44659fc00df3f03bc13872..9847987470b4876acb966b2294b7343c01f45af6 100644 (file)
@@ -514,7 +514,7 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
                                opline->result_type |= EXT_TYPE_UNUSED;
                        }
                } else {
-                       while (opline>CG(active_op_array)->opcodes) {
+                       while (opline >= CG(active_op_array)->opcodes) {
                                if (opline->opcode == ZEND_FETCH_LIST &&
                                    opline->op1_type == IS_VAR &&
                                    opline->op1.var == op1->u.op.var) {
@@ -2937,10 +2937,23 @@ void zend_compile_new(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
        zend_op *opline;
        uint32_t opnum;
 
-       zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
+       if (zend_is_const_default_class_ref(class_ast)) {
+               class_node.op_type = IS_CONST;
+               ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast TSRMLS_CC));
+       } else {
+               zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
+       }
 
        opnum = get_next_op_number(CG(active_op_array));
-       zend_emit_op(result, ZEND_NEW, &class_node, NULL TSRMLS_CC);
+       opline = zend_emit_op(result, ZEND_NEW, NULL, NULL TSRMLS_CC);
+
+       if (class_node.op_type == IS_CONST) {
+               opline->op1_type = IS_CONST;
+               opline->op1.constant = zend_add_class_name_literal(
+                       CG(active_op_array), Z_STR(class_node.u.constant) TSRMLS_CC);
+       } else {
+               SET_NODE(opline->op1, &class_node);
+       }
 
        zend_compile_call_common(&ctor_result, args_ast, NULL TSRMLS_CC);
        zend_do_free(&ctor_result TSRMLS_CC);
index 42ad32bbb68725d3d236f336ac6036ab3eb99a34..9171feaadd88d386bbba7a02ab9a0edcd37cd3c2 100644 (file)
@@ -3635,23 +3635,38 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
        ZEND_VM_NEXT_OPCODE();
 }
 
-ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
+ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
 {
        USE_OPLINE
        zval object_zval;
        zend_function *constructor;
+       zend_class_entry *ce;
 
        SAVE_OPLINE();
-       if (UNEXPECTED((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
-               if (Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_INTERFACE) {
-                       zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val);
-               } else if ((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
-                       zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val);
+       if (OP1_TYPE == IS_CONST) {
+               if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
+                       ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               CHECK_EXCEPTION();
+                               ZEND_VM_NEXT_OPCODE();
+                       }
+                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
+               }
+       } else {
+               ce = Z_CE_P(EX_VAR(opline->op1.var));
+       }
+       if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
+               if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+                       zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val);
+               } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+                       zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val);
                } else {
-                       zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val);
+                       zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val);
                }
        }
-       object_init_ex(&object_zval, Z_CE_P(EX_VAR(opline->op1.var)));
+       object_init_ex(&object_zval, ce);
        constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC);
 
        if (constructor == NULL) {
@@ -3670,7 +3685,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
                                        ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)),
                        constructor,
                        opline->extended_value,
-                       Z_CE_P(EX_VAR(opline->op1.var)),
+                       ce,
                        Z_OBJ(object_zval),
                        EX(call) TSRMLS_CC);
 
index f2dae2acbaa3b409f3255f8023b88a1071647afa..1bbeb4960d2bb24fa7b7eb8c08d19b5554000e5c 100644 (file)
@@ -1023,57 +1023,6 @@ static int ZEND_FASTCALL  ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
        ZEND_VM_NEXT_OPCODE();
 }
 
-static int ZEND_FASTCALL  ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-       USE_OPLINE
-       zval object_zval;
-       zend_function *constructor;
-
-       SAVE_OPLINE();
-       if (UNEXPECTED((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
-               if (Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_INTERFACE) {
-                       zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val);
-               } else if ((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
-                       zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val);
-               } else {
-                       zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val);
-               }
-       }
-       object_init_ex(&object_zval, Z_CE_P(EX_VAR(opline->op1.var)));
-       constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC);
-
-       if (constructor == NULL) {
-               if (RETURN_VALUE_USED(opline)) {
-                       ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval);
-               } else {
-                       zval_ptr_dtor(&object_zval);
-               }
-               ZEND_VM_JMP(opline->op2.jmp_addr);
-       } else {
-               /* We are not handling overloaded classes right now */
-               EX(call) = zend_vm_stack_push_call_frame(
-                       VM_FRAME_INFO(
-                               VM_FRAME_NESTED_FUNCTION,
-                               RETURN_VALUE_USED(opline) ?
-                                       ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)),
-                       constructor,
-                       opline->extended_value,
-                       Z_CE_P(EX_VAR(opline->op1.var)),
-                       Z_OBJ(object_zval),
-                       EX(call) TSRMLS_CC);
-
-               if (RETURN_VALUE_USED(opline)) {
-                       ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
-                       EX(call)->return_value = EX_VAR(opline->result.var);
-               } else {
-                       EX(call)->return_value = NULL;
-               }
-
-               CHECK_EXCEPTION();
-               ZEND_VM_NEXT_OPCODE();
-       }
-}
-
 static int ZEND_FASTCALL  ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -2769,6 +2718,72 @@ static int ZEND_FASTCALL  ZEND_BOOL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FASTCALL  ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zval object_zval;
+       zend_function *constructor;
+       zend_class_entry *ce;
+
+       SAVE_OPLINE();
+       if (IS_CONST == IS_CONST) {
+               if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
+                       ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               CHECK_EXCEPTION();
+                               ZEND_VM_NEXT_OPCODE();
+                       }
+                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
+               }
+       } else {
+               ce = Z_CE_P(EX_VAR(opline->op1.var));
+       }
+       if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
+               if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+                       zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val);
+               } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+                       zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val);
+               } else {
+                       zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val);
+               }
+       }
+       object_init_ex(&object_zval, ce);
+       constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC);
+
+       if (constructor == NULL) {
+               if (RETURN_VALUE_USED(opline)) {
+                       ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval);
+               } else {
+                       zval_ptr_dtor(&object_zval);
+               }
+               ZEND_VM_JMP(opline->op2.jmp_addr);
+       } else {
+               /* We are not handling overloaded classes right now */
+               EX(call) = zend_vm_stack_push_call_frame(
+                       VM_FRAME_INFO(
+                               VM_FRAME_NESTED_FUNCTION,
+                               RETURN_VALUE_USED(opline) ?
+                                       ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)),
+                       constructor,
+                       opline->extended_value,
+                       ce,
+                       Z_OBJ(object_zval),
+                       EX(call) TSRMLS_CC);
+
+               if (RETURN_VALUE_USED(opline)) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
+                       EX(call)->return_value = EX_VAR(opline->result.var);
+               } else {
+                       EX(call)->return_value = NULL;
+               }
+
+               CHECK_EXCEPTION();
+               ZEND_VM_NEXT_OPCODE();
+       }
+}
+
 static int ZEND_FASTCALL  ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -16302,6 +16317,72 @@ static int ZEND_FASTCALL  ZEND_BOOL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FASTCALL  ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zval object_zval;
+       zend_function *constructor;
+       zend_class_entry *ce;
+
+       SAVE_OPLINE();
+       if (IS_VAR == IS_CONST) {
+               if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
+                       ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               CHECK_EXCEPTION();
+                               ZEND_VM_NEXT_OPCODE();
+                       }
+                       CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
+               }
+       } else {
+               ce = Z_CE_P(EX_VAR(opline->op1.var));
+       }
+       if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
+               if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+                       zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val);
+               } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+                       zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val);
+               } else {
+                       zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val);
+               }
+       }
+       object_init_ex(&object_zval, ce);
+       constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC);
+
+       if (constructor == NULL) {
+               if (RETURN_VALUE_USED(opline)) {
+                       ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval);
+               } else {
+                       zval_ptr_dtor(&object_zval);
+               }
+               ZEND_VM_JMP(opline->op2.jmp_addr);
+       } else {
+               /* We are not handling overloaded classes right now */
+               EX(call) = zend_vm_stack_push_call_frame(
+                       VM_FRAME_INFO(
+                               VM_FRAME_NESTED_FUNCTION,
+                               RETURN_VALUE_USED(opline) ?
+                                       ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)),
+                       constructor,
+                       opline->extended_value,
+                       ce,
+                       Z_OBJ(object_zval),
+                       EX(call) TSRMLS_CC);
+
+               if (RETURN_VALUE_USED(opline)) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
+                       EX(call)->return_value = EX_VAR(opline->result.var);
+               } else {
+                       EX(call)->return_value = NULL;
+               }
+
+               CHECK_EXCEPTION();
+               ZEND_VM_NEXT_OPCODE();
+       }
+}
+
 static int ZEND_FASTCALL  ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -45345,31 +45426,31 @@ void zend_init_opcodes_handlers(void)
        ZEND_SEND_REF_SPEC_CV_HANDLER,
        ZEND_SEND_REF_SPEC_CV_HANDLER,
        ZEND_SEND_REF_SPEC_CV_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
-       ZEND_NEW_SPEC_HANDLER,
+       ZEND_NEW_SPEC_CONST_HANDLER,
+       ZEND_NEW_SPEC_CONST_HANDLER,
+       ZEND_NEW_SPEC_CONST_HANDLER,
+       ZEND_NEW_SPEC_CONST_HANDLER,
+       ZEND_NEW_SPEC_CONST_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NEW_SPEC_VAR_HANDLER,
+       ZEND_NEW_SPEC_VAR_HANDLER,
+       ZEND_NEW_SPEC_VAR_HANDLER,
+       ZEND_NEW_SPEC_VAR_HANDLER,
+       ZEND_NEW_SPEC_VAR_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
        ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
index 79f3c0435242184718ef5c205450110ac9ebd2f5..8fb5a9b0c92d6c47da89b7d079e4df2a04e0429a 100644 (file)
@@ -232,6 +232,11 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
                                                LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
                                        }
                                        break;
+                               case ZEND_NEW:
+                                       if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+                                               LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
+                                       }
+                                       break;
                                case ZEND_ASSIGN_OBJ:
                                case ZEND_FETCH_OBJ_R:
                                case ZEND_FETCH_OBJ_W:
index fb40349d27ab3bffd0d9e611fa12621b395b5264..1a6d0b675afa510c5c5ddd5bc83a184cfaf8c99d 100644 (file)
@@ -126,6 +126,7 @@ void zend_optimizer_update_op1_const(zend_op_array *op_array,
                                case ZEND_CATCH:
                                case ZEND_FETCH_CONSTANT:
                                case ZEND_DEFINED:
+                               case ZEND_NEW:
                                        opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
                                        zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline)));
                                        Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->last_cache_slot++;
index 44078733d6664817bbb076b1d681eb44bdcdbaaa..1de8e021dd9514d818e01972c22f179c9e6d5f66 100644 (file)
@@ -351,7 +351,9 @@ PHP_FUNCTION(spl_autoload)
                while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
                        ex = ex->prev_execute_data;
                }
-               if (ex && ex->opline->opcode != ZEND_FETCH_CLASS) {
+               if (ex &&
+                   ex->opline->opcode != ZEND_FETCH_CLASS &&
+                   ex->opline->opcode != ZEND_NEW) {
                        zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Class %s could not be loaded", class_name->val);
                } else {
                        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s could not be loaded", class_name->val);