]> granicus.if.org Git - php/commitdiff
Speed-up of ZEND_DO_FCALL and ZEND_INIT_FCALL_BY_NAME by lowercasing and calculating...
authorDmitry Stogov <dmitry@php.net>
Thu, 22 Nov 2007 09:03:11 +0000 (09:03 +0000)
committerDmitry Stogov <dmitry@php.net>
Thu, 22 Nov 2007 09:03:11 +0000 (09:03 +0000)
Zend/zend_compile.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_opcodes.h

index 9facc210bb20ff7330fce051dc99432c9026c225..f49bbcf1c653ca9f7b6ee31ed6500fecca547221 100644 (file)
@@ -1528,6 +1528,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
 {
        zend_op *last_op;
        int last_op_number;
+       unsigned int len;
        unsigned char *ptr = NULL;
 
        zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
@@ -1558,8 +1559,16 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
                zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                opline->opcode = ZEND_INIT_FCALL_BY_NAME;
                opline->op2 = *left_bracket;
-               opline->extended_value = 0;
-               SET_UNUSED(opline->op1);
+               if (opline->op2.op_type == IS_CONST) {
+                       opline->op1.op_type = IS_CONST;
+                       Z_TYPE(opline->op1.u.constant) = Z_TYPE(opline->op2.u.constant);
+                       Z_UNIVAL(opline->op1.u.constant) = zend_u_str_case_fold(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), 0, &len);
+                       Z_UNILEN(opline->op1.u.constant) = len;
+                       opline->extended_value = zend_u_hash_func(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant) + 1);
+               } else {
+                       opline->extended_value = 0;
+                       SET_UNUSED(opline->op1);
+               }
        }
 
        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
@@ -1583,20 +1592,48 @@ void zend_do_clone(znode *result, znode *expr TSRMLS_DC) /* {{{ */
 void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TSRMLS_DC) /* {{{ */
 {
        unsigned char *ptr = NULL;
+       unsigned int len;
        zend_op *opline;
 
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-       opline->opcode = ZEND_INIT_FCALL_BY_NAME;
-       opline->op2 = *function_name;
-       opline->extended_value = 0;
 
        if (prefix_len) {
                /* In run-time PHP will check for function with full name and
                   internal function with short name */
+               opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
+               opline->op2 = *function_name;
+               opline->extended_value = 0;
                opline->op1.op_type = IS_CONST;
-               ZVAL_LONG(&opline->op1.u.constant, prefix_len);
+               Z_TYPE(opline->op1.u.constant) = Z_TYPE(opline->op2.u.constant);
+               Z_UNIVAL(opline->op1.u.constant) = zend_u_str_case_fold(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), 0, &len);
+               Z_UNILEN(opline->op1.u.constant) = len;
+               opline->extended_value = zend_u_hash_func(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant) + 1);
+               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+               opline->opcode = ZEND_OP_DATA;
+               opline->op1.op_type = IS_CONST;
+               if (Z_TYPE(function_name->u.constant) == IS_UNICODE) {
+                       Z_TYPE(opline->op1.u.constant) = IS_UNICODE;
+                       Z_UNIVAL(opline->op1.u.constant) = zend_u_str_case_fold(IS_UNICODE, ZSTR(Z_USTRVAL(function_name->u.constant) + prefix_len), Z_USTRLEN(function_name->u.constant) - prefix_len, 0, &len);
+                       Z_UNILEN(opline->op1.u.constant) = len;
+               } else {
+                       Z_TYPE(opline->op1.u.constant) = IS_STRING;
+                       Z_STRLEN(opline->op1.u.constant) = Z_STRLEN(function_name->u.constant) - prefix_len;
+                       Z_STRVAL(opline->op1.u.constant) = zend_str_tolower_dup(Z_STRVAL(function_name->u.constant) + prefix_len, Z_STRLEN(opline->op1.u.constant));
+               }
+               opline->extended_value = zend_u_hash_func(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant) + 1);
        } else {
-               SET_UNUSED(opline->op1);
+               opline->opcode = ZEND_INIT_FCALL_BY_NAME;
+               opline->op2 = *function_name;
+               if (opline->op2.op_type == IS_CONST) {
+                       opline->op1.op_type = IS_CONST;
+                       Z_TYPE(opline->op1.u.constant) = Z_TYPE(opline->op2.u.constant);
+                       Z_UNIVAL(opline->op1.u.constant) = zend_u_str_case_fold(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), 0, &len);
+                       Z_UNILEN(opline->op1.u.constant) = len;
+                       opline->extended_value = zend_u_hash_func(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant) + 1);
+               } else {
+                       opline->extended_value = 0;
+                       SET_UNUSED(opline->op1);
+               }
        }
 
        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
@@ -1902,6 +1939,7 @@ void zend_do_end_function_call(znode *function_name, znode *result, znode *argum
                if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
                        opline->opcode = ZEND_DO_FCALL;
                        opline->op1 = *function_name;
+                       ZVAL_LONG(&opline->op2.u.constant, zend_u_hash_func(Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant), Z_UNILEN(function_name->u.constant) + 1));
                } else {
                        opline->opcode = ZEND_DO_FCALL_BY_NAME;
                        SET_UNUSED(opline->op1);
@@ -3900,6 +3938,7 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
                                           The additional names are stored in additional OP_DATA opcode. */
                                        zstr nsname;
                                        unsigned int nsname_len;
+                                       unsigned int len;
 
                                        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                                        opline->opcode = ZEND_OP_DATA;
@@ -3920,7 +3959,8 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
                                        }
 
                                        Z_TYPE(opline->op1.u.constant) = Z_TYPE(constant_container->u.constant);
-                                       Z_UNIVAL(opline->op1.u.constant) = zend_u_str_case_fold(Z_TYPE(constant_container->u.constant), nsname, nsname_len, 0, &Z_UNILEN(opline->op1.u.constant));
+                                       Z_UNIVAL(opline->op1.u.constant) = zend_u_str_case_fold(Z_TYPE(constant_container->u.constant), nsname, nsname_len, 0, &len);
+                                       Z_UNILEN(opline->op1.u.constant) = len;
                                        if (UG(unicode)) {
                                                Z_USTRVAL(opline->op1.u.constant) = erealloc(Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant) + 2 + Z_USTRLEN(constant_name->u.constant) + 1));
                                                Z_USTRVAL(opline->op1.u.constant)[Z_USTRLEN(opline->op1.u.constant)] = ':';
@@ -3970,6 +4010,7 @@ void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC) /* {{{ */
        opline->op1.op_type = IS_CONST;
        opline->extended_value = 1;
        SET_UNUSED(opline->op2);
+       ZVAL_LONG(&opline->op2.u.constant, zend_u_hash_func(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant)+1));
        *result = opline->result;
 }
 /* }}} */
index 7227a8fc46eaddffe4f93875e3fd4bb2f07c4462..cfc603266a4d89485a60ecc255adbd8e89906ee3 100644 (file)
@@ -1930,83 +1930,72 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
 {
        zend_op *opline = EX(opline);
        zval *function_name;
-       zend_function *function;
        zstr function_name_strval, lcname;
        unsigned int function_name_strlen, lcname_len;
        zend_free_op free_op2;
+       int ret;
 
        zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
        if (OP2_TYPE == IS_CONST) {
                function_name = &opline->op2.u.constant;
+               function_name_strval = Z_UNIVAL_P(function_name);
+               ret = zend_u_hash_quick_find(EG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc));
        } else {
                function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
 
                if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
                        zend_error_noreturn(E_ERROR, "Function name must be a string");
                }
-       }
-       function_name_strval = Z_UNIVAL_P(function_name);
-       function_name_strlen = Z_UNILEN_P(function_name);
-
-       if (OP2_TYPE != IS_CONST &&
-           ((Z_TYPE_P(function_name) == IS_UNICODE &&
-             Z_USTRVAL_P(function_name)[0] == ':' &&
-             Z_USTRVAL_P(function_name)[1] == ':') ||
-            (Z_TYPE_P(function_name) == IS_STRING &&
-             Z_STRVAL_P(function_name)[0] == ':' &&
-             Z_STRVAL_P(function_name)[1] == ':'))) {
-               if (Z_TYPE_P(function_name) == IS_UNICODE) {
-                       zstr tmp;
-
-                       tmp.u = Z_USTRVAL_P(function_name) + 2;
-                       lcname = zend_u_str_case_fold(IS_UNICODE, tmp, function_name_strlen-2, 1, &lcname_len);
+               function_name_strval = Z_UNIVAL_P(function_name);
+               function_name_strlen = Z_UNILEN_P(function_name);
+               if (Z_TYPE_P(function_name) == IS_UNICODE &&
+                   function_name_strval.u[0] == ':' &&
+                   function_name_strval.u[1] == ':') {
+                   function_name_strlen -= 2;
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), ZSTR(function_name_strval.u+2), function_name_strlen, 1, &lcname_len);
+               } else if (Z_TYPE_P(function_name) == IS_STRING &&
+                          function_name_strval.s[0] == ':' &&
+                          function_name_strval.s[1] == ':') {
+                   function_name_strlen -= 2;
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), ZSTR(function_name_strval.s+2), function_name_strlen, 1, &lcname_len);
                } else {
-                       zstr tmp;
-
-                       tmp.s = Z_STRVAL_P(function_name) + 2;
-                       lcname = zend_u_str_case_fold(IS_STRING, tmp, function_name_strlen-2, 1, &lcname_len);
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), function_name_strval, function_name_strlen, 1, &lcname_len);
                }
-       } else {
-               lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len);
-       }
-       if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
+               ret = zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &EX(fbc));
                efree(lcname.v);
-
-               if (OP2_TYPE == IS_CONST && opline->op1.op_type == IS_CONST) {
-                       if (Z_TYPE_P(function_name) == IS_UNICODE) {
-                               zstr tmp;
-
-                               tmp.u = Z_USTRVAL_P(function_name) + Z_LVAL(opline->op1.u.constant);
-                               lcname = zend_u_str_case_fold(IS_UNICODE, tmp, function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len);
-                       } else {
-                               zstr tmp;
-
-                               tmp.s = Z_STRVAL_P(function_name) + Z_LVAL(opline->op1.u.constant);
-                               lcname = zend_u_str_case_fold(IS_STRING, tmp, function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len);
-                       }
-                       if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE ||
-                           function->type != ZEND_INTERNAL_FUNCTION) {
-                               efree(lcname.v);
-                               zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
-                       }
-               } else {
-                       zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
-               }
+       }
+       if (ret==FAILURE) {
+               zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), Z_UNIVAL_P(function_name));
        }
 
-       efree(lcname.v);
        if (OP2_TYPE != IS_CONST) {
                FREE_OP2();
        }
 
        EX(object) = NULL;
 
-       EX(fbc) = function;
-
        ZEND_VM_NEXT_OPCODE();
 }
 
+ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
+{
+       zend_op *opline = EX(opline);
+       zend_op *op_data = opline + 1;
+
+       ZEND_VM_INC_OPCODE();
+       zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
+
+       if (zend_u_hash_quick_find(EG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc))==FAILURE) {
+               if (zend_u_hash_quick_find(EG(function_table), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==FAILURE ||
+                   EX(fbc)->type != ZEND_INTERNAL_FUNCTION) {
+                       zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE(opline->op2.u.constant), Z_USTRVAL(opline->op2.u.constant));
+               }
+       }
+
+       EX(object) = NULL;
+       ZEND_VM_NEXT_OPCODE();
+ }
 
 ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
 {
@@ -2209,7 +2198,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)
 
        zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
-       if (zend_u_hash_find(EG(function_table), Z_TYPE_P(fname), Z_UNIVAL_P(fname), Z_UNILEN_P(fname)+1, (void **) &EX(function_state).function)==FAILURE) {
+       if (zend_u_hash_quick_find(EG(function_table), Z_TYPE_P(fname), Z_UNIVAL_P(fname), Z_UNILEN_P(fname)+1, Z_LVAL(opline->op2.u.constant), (void **) &EX(function_state).function)==FAILURE) {
                /* FIXME: output identifiers properly */
                zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(fname), Z_UNIVAL_P(fname));
        }
@@ -2583,7 +2572,7 @@ ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
        ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
 }
 
-ZEND_VM_HANDLER(69, ZEND_GOTO, ANY, CONST)
+ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
 {
        zend_op *brk_opline;
        zend_op *opline = EX(opline);
index 02952a257c5e5134bab7f00e1b09d3be8805fe9d..3ba21f1a94c2cc029cb9388198f810245c3a60b0 100644 (file)
@@ -657,83 +657,72 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        zval *function_name;
-       zend_function *function;
        zstr function_name_strval, lcname;
        unsigned int function_name_strlen, lcname_len;
 
+       int ret;
 
        zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
        if (IS_CONST == IS_CONST) {
                function_name = &opline->op2.u.constant;
+               function_name_strval = Z_UNIVAL_P(function_name);
+               ret = zend_u_hash_quick_find(EG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc));
        } else {
                function_name = &opline->op2.u.constant;
 
                if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
                        zend_error_noreturn(E_ERROR, "Function name must be a string");
                }
-       }
-       function_name_strval = Z_UNIVAL_P(function_name);
-       function_name_strlen = Z_UNILEN_P(function_name);
-
-       if (IS_CONST != IS_CONST &&
-           ((Z_TYPE_P(function_name) == IS_UNICODE &&
-             Z_USTRVAL_P(function_name)[0] == ':' &&
-             Z_USTRVAL_P(function_name)[1] == ':') ||
-            (Z_TYPE_P(function_name) == IS_STRING &&
-             Z_STRVAL_P(function_name)[0] == ':' &&
-             Z_STRVAL_P(function_name)[1] == ':'))) {
-               if (Z_TYPE_P(function_name) == IS_UNICODE) {
-                       zstr tmp;
-
-                       tmp.u = Z_USTRVAL_P(function_name) + 2;
-                       lcname = zend_u_str_case_fold(IS_UNICODE, tmp, function_name_strlen-2, 1, &lcname_len);
+               function_name_strval = Z_UNIVAL_P(function_name);
+               function_name_strlen = Z_UNILEN_P(function_name);
+               if (Z_TYPE_P(function_name) == IS_UNICODE &&
+                   function_name_strval.u[0] == ':' &&
+                   function_name_strval.u[1] == ':') {
+                   function_name_strlen -= 2;
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), ZSTR(function_name_strval.u+2), function_name_strlen, 1, &lcname_len);
+               } else if (Z_TYPE_P(function_name) == IS_STRING &&
+                          function_name_strval.s[0] == ':' &&
+                          function_name_strval.s[1] == ':') {
+                   function_name_strlen -= 2;
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), ZSTR(function_name_strval.s+2), function_name_strlen, 1, &lcname_len);
                } else {
-                       zstr tmp;
-
-                       tmp.s = Z_STRVAL_P(function_name) + 2;
-                       lcname = zend_u_str_case_fold(IS_STRING, tmp, function_name_strlen-2, 1, &lcname_len);
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), function_name_strval, function_name_strlen, 1, &lcname_len);
                }
-       } else {
-               lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len);
-       }
-       if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
+               ret = zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &EX(fbc));
                efree(lcname.v);
-
-               if (IS_CONST == IS_CONST && opline->op1.op_type == IS_CONST) {
-                       if (Z_TYPE_P(function_name) == IS_UNICODE) {
-                               zstr tmp;
-
-                               tmp.u = Z_USTRVAL_P(function_name) + Z_LVAL(opline->op1.u.constant);
-                               lcname = zend_u_str_case_fold(IS_UNICODE, tmp, function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len);
-                       } else {
-                               zstr tmp;
-
-                               tmp.s = Z_STRVAL_P(function_name) + Z_LVAL(opline->op1.u.constant);
-                               lcname = zend_u_str_case_fold(IS_STRING, tmp, function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len);
-                       }
-                       if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE ||
-                           function->type != ZEND_INTERNAL_FUNCTION) {
-                               efree(lcname.v);
-                               zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
-                       }
-               } else {
-                       zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
-               }
+       }
+       if (ret==FAILURE) {
+               zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), Z_UNIVAL_P(function_name));
        }
 
-       efree(lcname.v);
        if (IS_CONST != IS_CONST) {
 
        }
 
        EX(object) = NULL;
 
-       EX(fbc) = function;
-
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       zend_op *opline = EX(opline);
+       zend_op *op_data = opline + 1;
+
+       ZEND_VM_INC_OPCODE();
+       zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
+
+       if (zend_u_hash_quick_find(EG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc))==FAILURE) {
+               if (zend_u_hash_quick_find(EG(function_table), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==FAILURE ||
+                   EX(fbc)->type != ZEND_INTERNAL_FUNCTION) {
+                       zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE(opline->op2.u.constant), Z_USTRVAL(opline->op2.u.constant));
+               }
+       }
+
+       EX(object) = NULL;
+       ZEND_VM_NEXT_OPCODE();
+ }
 
 static int ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
@@ -855,84 +844,54 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        zval *function_name;
-       zend_function *function;
        zstr function_name_strval, lcname;
        unsigned int function_name_strlen, lcname_len;
        zend_free_op free_op2;
+       int ret;
 
        zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
        if (IS_TMP_VAR == IS_CONST) {
                function_name = &opline->op2.u.constant;
+               function_name_strval = Z_UNIVAL_P(function_name);
+               ret = zend_u_hash_quick_find(EG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc));
        } else {
                function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
 
                if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
                        zend_error_noreturn(E_ERROR, "Function name must be a string");
                }
-       }
-       function_name_strval = Z_UNIVAL_P(function_name);
-       function_name_strlen = Z_UNILEN_P(function_name);
-
-       if (IS_TMP_VAR != IS_CONST &&
-           ((Z_TYPE_P(function_name) == IS_UNICODE &&
-             Z_USTRVAL_P(function_name)[0] == ':' &&
-             Z_USTRVAL_P(function_name)[1] == ':') ||
-            (Z_TYPE_P(function_name) == IS_STRING &&
-             Z_STRVAL_P(function_name)[0] == ':' &&
-             Z_STRVAL_P(function_name)[1] == ':'))) {
-               if (Z_TYPE_P(function_name) == IS_UNICODE) {
-                       zstr tmp;
-
-                       tmp.u = Z_USTRVAL_P(function_name) + 2;
-                       lcname = zend_u_str_case_fold(IS_UNICODE, tmp, function_name_strlen-2, 1, &lcname_len);
+               function_name_strval = Z_UNIVAL_P(function_name);
+               function_name_strlen = Z_UNILEN_P(function_name);
+               if (Z_TYPE_P(function_name) == IS_UNICODE &&
+                   function_name_strval.u[0] == ':' &&
+                   function_name_strval.u[1] == ':') {
+                   function_name_strlen -= 2;
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), ZSTR(function_name_strval.u+2), function_name_strlen, 1, &lcname_len);
+               } else if (Z_TYPE_P(function_name) == IS_STRING &&
+                          function_name_strval.s[0] == ':' &&
+                          function_name_strval.s[1] == ':') {
+                   function_name_strlen -= 2;
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), ZSTR(function_name_strval.s+2), function_name_strlen, 1, &lcname_len);
                } else {
-                       zstr tmp;
-
-                       tmp.s = Z_STRVAL_P(function_name) + 2;
-                       lcname = zend_u_str_case_fold(IS_STRING, tmp, function_name_strlen-2, 1, &lcname_len);
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), function_name_strval, function_name_strlen, 1, &lcname_len);
                }
-       } else {
-               lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len);
-       }
-       if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
+               ret = zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &EX(fbc));
                efree(lcname.v);
-
-               if (IS_TMP_VAR == IS_CONST && opline->op1.op_type == IS_CONST) {
-                       if (Z_TYPE_P(function_name) == IS_UNICODE) {
-                               zstr tmp;
-
-                               tmp.u = Z_USTRVAL_P(function_name) + Z_LVAL(opline->op1.u.constant);
-                               lcname = zend_u_str_case_fold(IS_UNICODE, tmp, function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len);
-                       } else {
-                               zstr tmp;
-
-                               tmp.s = Z_STRVAL_P(function_name) + Z_LVAL(opline->op1.u.constant);
-                               lcname = zend_u_str_case_fold(IS_STRING, tmp, function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len);
-                       }
-                       if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE ||
-                           function->type != ZEND_INTERNAL_FUNCTION) {
-                               efree(lcname.v);
-                               zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
-                       }
-               } else {
-                       zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
-               }
+       }
+       if (ret==FAILURE) {
+               zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), Z_UNIVAL_P(function_name));
        }
 
-       efree(lcname.v);
        if (IS_TMP_VAR != IS_CONST) {
                zval_dtor(free_op2.var);
        }
 
        EX(object) = NULL;
 
-       EX(fbc) = function;
-
        ZEND_VM_NEXT_OPCODE();
 }
 
-
 static int ZEND_FETCH_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
@@ -968,84 +927,54 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        zval *function_name;
-       zend_function *function;
        zstr function_name_strval, lcname;
        unsigned int function_name_strlen, lcname_len;
        zend_free_op free_op2;
+       int ret;
 
        zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
        if (IS_VAR == IS_CONST) {
                function_name = &opline->op2.u.constant;
+               function_name_strval = Z_UNIVAL_P(function_name);
+               ret = zend_u_hash_quick_find(EG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc));
        } else {
                function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
 
                if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
                        zend_error_noreturn(E_ERROR, "Function name must be a string");
                }
-       }
-       function_name_strval = Z_UNIVAL_P(function_name);
-       function_name_strlen = Z_UNILEN_P(function_name);
-
-       if (IS_VAR != IS_CONST &&
-           ((Z_TYPE_P(function_name) == IS_UNICODE &&
-             Z_USTRVAL_P(function_name)[0] == ':' &&
-             Z_USTRVAL_P(function_name)[1] == ':') ||
-            (Z_TYPE_P(function_name) == IS_STRING &&
-             Z_STRVAL_P(function_name)[0] == ':' &&
-             Z_STRVAL_P(function_name)[1] == ':'))) {
-               if (Z_TYPE_P(function_name) == IS_UNICODE) {
-                       zstr tmp;
-
-                       tmp.u = Z_USTRVAL_P(function_name) + 2;
-                       lcname = zend_u_str_case_fold(IS_UNICODE, tmp, function_name_strlen-2, 1, &lcname_len);
+               function_name_strval = Z_UNIVAL_P(function_name);
+               function_name_strlen = Z_UNILEN_P(function_name);
+               if (Z_TYPE_P(function_name) == IS_UNICODE &&
+                   function_name_strval.u[0] == ':' &&
+                   function_name_strval.u[1] == ':') {
+                   function_name_strlen -= 2;
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), ZSTR(function_name_strval.u+2), function_name_strlen, 1, &lcname_len);
+               } else if (Z_TYPE_P(function_name) == IS_STRING &&
+                          function_name_strval.s[0] == ':' &&
+                          function_name_strval.s[1] == ':') {
+                   function_name_strlen -= 2;
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), ZSTR(function_name_strval.s+2), function_name_strlen, 1, &lcname_len);
                } else {
-                       zstr tmp;
-
-                       tmp.s = Z_STRVAL_P(function_name) + 2;
-                       lcname = zend_u_str_case_fold(IS_STRING, tmp, function_name_strlen-2, 1, &lcname_len);
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), function_name_strval, function_name_strlen, 1, &lcname_len);
                }
-       } else {
-               lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len);
-       }
-       if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
+               ret = zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &EX(fbc));
                efree(lcname.v);
-
-               if (IS_VAR == IS_CONST && opline->op1.op_type == IS_CONST) {
-                       if (Z_TYPE_P(function_name) == IS_UNICODE) {
-                               zstr tmp;
-
-                               tmp.u = Z_USTRVAL_P(function_name) + Z_LVAL(opline->op1.u.constant);
-                               lcname = zend_u_str_case_fold(IS_UNICODE, tmp, function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len);
-                       } else {
-                               zstr tmp;
-
-                               tmp.s = Z_STRVAL_P(function_name) + Z_LVAL(opline->op1.u.constant);
-                               lcname = zend_u_str_case_fold(IS_STRING, tmp, function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len);
-                       }
-                       if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE ||
-                           function->type != ZEND_INTERNAL_FUNCTION) {
-                               efree(lcname.v);
-                               zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
-                       }
-               } else {
-                       zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
-               }
+       }
+       if (ret==FAILURE) {
+               zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), Z_UNIVAL_P(function_name));
        }
 
-       efree(lcname.v);
        if (IS_VAR != IS_CONST) {
                if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
        }
 
        EX(object) = NULL;
 
-       EX(fbc) = function;
-
        ZEND_VM_NEXT_OPCODE();
 }
 
-
 static int ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
@@ -1110,84 +1039,54 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        zval *function_name;
-       zend_function *function;
        zstr function_name_strval, lcname;
        unsigned int function_name_strlen, lcname_len;
 
+       int ret;
 
        zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
        if (IS_CV == IS_CONST) {
                function_name = &opline->op2.u.constant;
+               function_name_strval = Z_UNIVAL_P(function_name);
+               ret = zend_u_hash_quick_find(EG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc));
        } else {
                function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
 
                if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
                        zend_error_noreturn(E_ERROR, "Function name must be a string");
                }
-       }
-       function_name_strval = Z_UNIVAL_P(function_name);
-       function_name_strlen = Z_UNILEN_P(function_name);
-
-       if (IS_CV != IS_CONST &&
-           ((Z_TYPE_P(function_name) == IS_UNICODE &&
-             Z_USTRVAL_P(function_name)[0] == ':' &&
-             Z_USTRVAL_P(function_name)[1] == ':') ||
-            (Z_TYPE_P(function_name) == IS_STRING &&
-             Z_STRVAL_P(function_name)[0] == ':' &&
-             Z_STRVAL_P(function_name)[1] == ':'))) {
-               if (Z_TYPE_P(function_name) == IS_UNICODE) {
-                       zstr tmp;
-
-                       tmp.u = Z_USTRVAL_P(function_name) + 2;
-                       lcname = zend_u_str_case_fold(IS_UNICODE, tmp, function_name_strlen-2, 1, &lcname_len);
+               function_name_strval = Z_UNIVAL_P(function_name);
+               function_name_strlen = Z_UNILEN_P(function_name);
+               if (Z_TYPE_P(function_name) == IS_UNICODE &&
+                   function_name_strval.u[0] == ':' &&
+                   function_name_strval.u[1] == ':') {
+                   function_name_strlen -= 2;
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), ZSTR(function_name_strval.u+2), function_name_strlen, 1, &lcname_len);
+               } else if (Z_TYPE_P(function_name) == IS_STRING &&
+                          function_name_strval.s[0] == ':' &&
+                          function_name_strval.s[1] == ':') {
+                   function_name_strlen -= 2;
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), ZSTR(function_name_strval.s+2), function_name_strlen, 1, &lcname_len);
                } else {
-                       zstr tmp;
-
-                       tmp.s = Z_STRVAL_P(function_name) + 2;
-                       lcname = zend_u_str_case_fold(IS_STRING, tmp, function_name_strlen-2, 1, &lcname_len);
+                       lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), function_name_strval, function_name_strlen, 1, &lcname_len);
                }
-       } else {
-               lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len);
-       }
-       if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
+               ret = zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &EX(fbc));
                efree(lcname.v);
-
-               if (IS_CV == IS_CONST && opline->op1.op_type == IS_CONST) {
-                       if (Z_TYPE_P(function_name) == IS_UNICODE) {
-                               zstr tmp;
-
-                               tmp.u = Z_USTRVAL_P(function_name) + Z_LVAL(opline->op1.u.constant);
-                               lcname = zend_u_str_case_fold(IS_UNICODE, tmp, function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len);
-                       } else {
-                               zstr tmp;
-
-                               tmp.s = Z_STRVAL_P(function_name) + Z_LVAL(opline->op1.u.constant);
-                               lcname = zend_u_str_case_fold(IS_STRING, tmp, function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len);
-                       }
-                       if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE ||
-                           function->type != ZEND_INTERNAL_FUNCTION) {
-                               efree(lcname.v);
-                               zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
-                       }
-               } else {
-                       zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
-               }
+       }
+       if (ret==FAILURE) {
+               zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), Z_UNIVAL_P(function_name));
        }
 
-       efree(lcname.v);
        if (IS_CV != IS_CONST) {
 
        }
 
        EX(object) = NULL;
 
-       EX(fbc) = function;
-
        ZEND_VM_NEXT_OPCODE();
 }
 
-
 static int ZEND_BW_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
@@ -1492,7 +1391,7 @@ static int ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 
        zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
-       if (zend_u_hash_find(EG(function_table), Z_TYPE_P(fname), Z_UNIVAL_P(fname), Z_UNILEN_P(fname)+1, (void **) &EX(function_state).function)==FAILURE) {
+       if (zend_u_hash_quick_find(EG(function_table), Z_TYPE_P(fname), Z_UNIVAL_P(fname), Z_UNILEN_P(fname)+1, Z_LVAL(opline->op2.u.constant), (void **) &EX(function_state).function)==FAILURE) {
                /* FIXME: output identifiers properly */
                zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(fname), Z_UNIVAL_P(fname));
        }
@@ -30933,27 +30832,27 @@ void zend_init_opcodes_handlers(void)
        ZEND_NEW_SPEC_HANDLER,
        ZEND_NEW_SPEC_HANDLER,
        ZEND_NEW_SPEC_HANDLER,
-       ZEND_GOTO_SPEC_CONST_HANDLER,
+       ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
-       ZEND_GOTO_SPEC_CONST_HANDLER,
+       ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
-       ZEND_GOTO_SPEC_CONST_HANDLER,
+       ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
-       ZEND_GOTO_SPEC_CONST_HANDLER,
+       ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
-       ZEND_GOTO_SPEC_CONST_HANDLER,
+       ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
@@ -31708,27 +31607,27 @@ void zend_init_opcodes_handlers(void)
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
+       ZEND_GOTO_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
+       ZEND_GOTO_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
+       ZEND_GOTO_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
+       ZEND_GOTO_SPEC_CONST_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_GOTO_SPEC_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
index b1d88da2134928653da5f0525802620443268688..d48887b5a0568ec0459e1e9fea41a076e1aa84ac 100644 (file)
@@ -87,7 +87,7 @@
 #define ZEND_SEND_VAR                 66
 #define ZEND_SEND_REF                 67
 #define ZEND_NEW                      68
-#define ZEND_GOTO                     69
+#define ZEND_INIT_NS_FCALL_BY_NAME    69
 #define ZEND_FREE                     70
 #define ZEND_INIT_ARRAY               71
 #define ZEND_ADD_ARRAY_ELEMENT        72
 #define ZEND_FETCH_OBJ_UNSET          97
 #define ZEND_FETCH_DIM_TMP_VAR        98
 #define ZEND_FETCH_CONSTANT           99
+#define ZEND_GOTO                    100
 #define ZEND_EXT_STMT                101
 #define ZEND_EXT_FCALL_BEGIN         102
 #define ZEND_EXT_FCALL_END           103