]> granicus.if.org Git - php/commitdiff
* Fix a by-name call/method call bug
authorAndi Gutmans <andi@php.net>
Tue, 8 Jun 1999 18:33:31 +0000 (18:33 +0000)
committerAndi Gutmans <andi@php.net>
Tue, 8 Jun 1999 18:33:31 +0000 (18:33 +0000)
* Clean and optimize the whole function call process

Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c

index 1ba8e444f35cec50ea308839d14b7cd1dc8ef805..ddc09edbe6d7a181ce4fa35fee41fa295d34e32f 100644 (file)
@@ -682,7 +682,6 @@ void do_receive_arg(int op, znode *var, znode *offset, znode *initialization, un
 
 void do_begin_function_call(znode *function_name CLS_DC)
 {
-       zend_op *opline ;
        zend_function *function;
        
        zend_str_tolower(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len);
@@ -694,8 +693,6 @@ void do_begin_function_call(znode *function_name CLS_DC)
                return;
        }
        
-       opline = get_next_op(CG(active_op_array) CLS_CC);
-
        switch (function->type) {
                case ZEND_USER_FUNCTION:        {
                                zend_op_array *op_array = (zend_op_array *) function;
@@ -710,9 +707,6 @@ void do_begin_function_call(znode *function_name CLS_DC)
                        }
                        break;
        }
-       opline->opcode = ZEND_INIT_FCALL;
-       SET_UNUSED(opline->op1);
-       SET_UNUSED(opline->op2);
 }
 
 
@@ -756,7 +750,11 @@ void do_end_function_call(znode *function_name, znode *result, znode *argument_l
        zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
        ELS_FETCH();
        
-       opline->opcode = ZEND_DO_FCALL;
+       if (function_name->op_type==IS_CONST && !is_method) {
+               opline->opcode = ZEND_DO_FCALL;
+       } else {
+               opline->opcode = ZEND_DO_FCALL_BY_NAME;
+       }
        opline->op1 = *function_name;
        opline->result.u.var = get_temporary_variable(CG(active_op_array));
        opline->result.op_type = IS_TMP_VAR;
@@ -779,8 +777,10 @@ void do_pass_param(znode *param, int op, int offset CLS_DC)
        function_ptr = *function_ptr_ptr;
        if (function_ptr) {
                arg_types = function_ptr->common.arg_types;
+               opline->extended_value = ZEND_DO_FCALL;
        } else {
                arg_types = NULL;
+               opline->extended_value = ZEND_DO_FCALL_BY_NAME;
        }
 
        if (op == ZEND_SEND_VAL) {
@@ -1350,11 +1350,6 @@ void do_shell_exec(znode *result, znode *cmd CLS_DC)
 {
        zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
 
-       opline->opcode = ZEND_INIT_FCALL;
-       SET_UNUSED(opline->op1);
-       SET_UNUSED(opline->op2);
-
-       opline = get_next_op(CG(active_op_array) CLS_CC);
        switch (cmd->op_type) {
                case IS_TMP_VAR:
                        opline->opcode = ZEND_SEND_VAL;
@@ -1365,6 +1360,7 @@ void do_shell_exec(znode *result, znode *cmd CLS_DC)
        }
        opline->op1 = *cmd;
        opline->op2.u.opline_num = 0;
+       opline->extended_value = ZEND_DO_FCALL;
        SET_UNUSED(opline->op2);
 
        opline = get_next_op(CG(active_op_array) CLS_CC);
index 75a3f1ce37fe458e6faa0cbb226d69d53ff0b570..1b704447e64888c9d1abdf66589d77dae91650a1 100644 (file)
@@ -433,9 +433,9 @@ int zendlex(znode *zendlval CLS_DC);
 #define ZEND_BEGIN_SILENCE                     54
 #define ZEND_END_SILENCE                       55
 
-#define ZEND_INIT_FCALL                                56
-#define ZEND_INIT_FCALL_BY_NAME                57
-#define ZEND_DO_FCALL                          58
+#define ZEND_INIT_FCALL_BY_NAME                56
+#define ZEND_DO_FCALL                          57
+#define ZEND_DO_FCALL_BY_NAME          58
 #define ZEND_RETURN                                    59
 
 #define ZEND_RECV                                      60
index 39dd7be2f47213aa32e059effa372fa5cab7b5d6..8b942584a9e33ec51eb70169b9d6dd4922d57e09 100644 (file)
@@ -1247,6 +1247,9 @@ binary_assign_op_addr: {
                                        HashTable *active_function_table;
                                        zval tmp;
 
+                                       zend_ptr_stack_push(&EG(arg_types_stack), function_being_called); 
+                                       zend_ptr_stack_push(&EG(arg_types_stack), object_ptr); 
+
                                        if (opline->extended_value & ZEND_CTOR_CALL) {
                                                /* constructor call */
                                                EG(AiCount)++; /* for op1 */
@@ -1319,28 +1322,25 @@ binary_assign_op_addr: {
                                        zval_dtor(&tmp);
                                        function_being_called = function;
 overloaded_function_call_cont:
-                                       zend_ptr_stack_push(&EG(arg_types_stack), function_being_called); 
                                        FREE_OP(&opline->op2, free_op2);
                                }
                                break;
-                       case ZEND_INIT_FCALL:
-                               object_ptr=NULL;
-                               function_being_called=NULL;
-                               break;
+                       case ZEND_DO_FCALL_BY_NAME:
+                               function_state.function = function_being_called;
+                               goto do_fcall_common;
                        case ZEND_DO_FCALL: {
-                                       zval *original_return_value;
+                                       zval *fname = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R);
 
-                                       if (function_being_called) {
-                                               function_being_called = zend_ptr_stack_pop(&EG(arg_types_stack));
-                                               function_state.function = function_being_called;
-                                       } else {
-                                               zval *fname = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R);
-                                               
-                                               if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &function_state.function)==FAILURE) {
-                                                       zend_error(E_ERROR, "Unknown function:  %s()\n", fname->value.str.val);
-                                               }
-                                               FREE_OP(&opline->op1, free_op1);
+                                       if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &function_state.function)==FAILURE) {
+                                               zend_error(E_ERROR, "Unknown function:  %s()\n", fname->value.str.val);
                                        }
+                                       FREE_OP(&opline->op1, free_op1);
+                                       goto do_fcall_common;
+                               }
+do_fcall_common:
+                               {
+                                       zval *original_return_value;
+
                                        zend_ptr_stack_push(&EG(argument_stack), (void *) opline->extended_value);
                                        if (function_state.function->type==ZEND_INTERNAL_FUNCTION) {
                                                var_uninit(&Ts[opline->result.u.var].tmp_var);
@@ -1356,7 +1356,9 @@ overloaded_function_call_cont:
                                                }
                                                calling_symbol_table = EG(active_symbol_table);
                                                EG(active_symbol_table) = function_state.function_symbol_table;
-                                               if (object_ptr && function_being_called && function_being_called->type!=ZEND_OVERLOADED_FUNCTION) {
+                                               if (opline->opcode==ZEND_DO_FCALL_BY_NAME
+                                                       && object_ptr
+                                                       && function_being_called->type!=ZEND_OVERLOADED_FUNCTION) {
                                                        zval *dummy = (zval *) emalloc(sizeof(zval)), **this_ptr;
 
                                                        var_uninit(dummy);
@@ -1386,7 +1388,10 @@ overloaded_function_call_cont:
                                                call_overloaded_function(opline->extended_value, &Ts[opline->result.u.var].tmp_var, &EG(regular_list), &EG(persistent_list) ELS_CC);
                                                efree(function_being_called);
                                        }
-                                       function_being_called = NULL;
+                                       if (opline->opcode == ZEND_DO_FCALL_BY_NAME) {
+                                               object_ptr = zend_ptr_stack_pop(&EG(arg_types_stack));
+                                               function_being_called = zend_ptr_stack_pop(&EG(arg_types_stack));
+                                       }
                                        function_state.function = (zend_function *) op_array;
                                        EG(function_state_ptr) = &function_state;
                                        zend_ptr_stack_clear_multiple(ELS_C);
@@ -1409,7 +1414,8 @@ overloaded_function_call_cont:
                                }
                                break;
                        case ZEND_SEND_VAL: 
-                               if (function_being_called
+                               if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
+                                       && function_being_called
                                        && function_being_called->common.arg_types
                                        && opline->op2.u.opline_num<=function_being_called->common.arg_types[0]
                                        && function_being_called->common.arg_types[opline->op2.u.opline_num]==BYREF_FORCE) {
@@ -1426,7 +1432,8 @@ overloaded_function_call_cont:
                                }
                                break;
                        case ZEND_SEND_VAR:
-                               if (function_being_called
+                               if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
+                                       && function_being_called
                                        && function_being_called->common.arg_types
                                        && opline->op2.u.opline_num<=function_being_called->common.arg_types[0]
                                        && function_being_called->common.arg_types[opline->op2.u.opline_num]==BYREF_FORCE) {