]> granicus.if.org Git - php/commitdiff
This patch is a go. Not fully optimized yet, but working properly.
authorZeev Suraski <zeev@php.net>
Mon, 12 Apr 1999 18:29:09 +0000 (18:29 +0000)
committerZeev Suraski <zeev@php.net>
Mon, 12 Apr 1999 18:29:09 +0000 (18:29 +0000)
Prepatch tagged as BEFORE_STACK_PATCH.

Zend/zend-parser.y
Zend/zend.h
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_execute_API.c
Zend/zend_globals.h
Zend/zend_ptr_stack.c

index a3f22364ab82b510ab66e0dcbe182966fc1bdf22..1fab94d93d1581573243abb194fd3ac74a003e5d 100644 (file)
@@ -253,10 +253,10 @@ parameter_list:
 
 
 non_empty_parameter_list:
-               VARIABLE                                                { znode tmp;  fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=0; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }
-       |       '&' VARIABLE                                    { znode tmp;  fetch_simple_variable(&tmp, &$2, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=0; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_FORCE CLS_CC); }
-       |       ZEND_CONST VARIABLE                     { znode tmp;  fetch_simple_variable(&tmp, &$2, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=0; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }
-       |       VARIABLE '=' static_scalar              { znode tmp;  fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=0; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$3, BYREF_NONE CLS_CC); }
+               VARIABLE                                                { znode tmp;  fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }
+       |       '&' VARIABLE                                    { znode tmp;  fetch_simple_variable(&tmp, &$2, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_FORCE CLS_CC); }
+       |       ZEND_CONST VARIABLE                     { znode tmp;  fetch_simple_variable(&tmp, &$2, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }
+       |       VARIABLE '=' static_scalar              { znode tmp;  fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$3, BYREF_NONE CLS_CC); }
        |       non_empty_parameter_list ',' VARIABLE                                           { znode tmp;  fetch_simple_variable(&tmp, &$3, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }
        |       non_empty_parameter_list ',' '&' VARIABLE                                       { znode tmp;  fetch_simple_variable(&tmp, &$4, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_FORCE CLS_CC); }
        |       non_empty_parameter_list ',' ZEND_CONST VARIABLE                        { znode tmp;  fetch_simple_variable(&tmp, &$4, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }
@@ -265,15 +265,15 @@ non_empty_parameter_list:
 
 
 function_call_parameter_list:
-               non_empty_function_call_parameter_list
-       |       /* empty */
+               non_empty_function_call_parameter_list          { $$ = $1; }
+       |       /* empty */                                                                     { $$.u.constant.value.lval = 0; }
 ;
 
 
 non_empty_function_call_parameter_list:
-               expr_without_variable   {       $$.u.constant.value.lval = 0;  do_pass_param(&$1, ZEND_SEND_VAL, $$.u.constant.value.lval CLS_CC); }
-       |       cvar                                    {       $$.u.constant.value.lval = 0;  do_pass_param(&$1, ZEND_SEND_VAR, $$.u.constant.value.lval CLS_CC); }
-       |       '&' w_cvar                              {       $$.u.constant.value.lval = 0;  do_pass_param(&$2, ZEND_SEND_REF, $$.u.constant.value.lval CLS_CC); }
+               expr_without_variable   {       $$.u.constant.value.lval = 1;  do_pass_param(&$1, ZEND_SEND_VAL, $$.u.constant.value.lval CLS_CC); }
+       |       cvar                                    {       $$.u.constant.value.lval = 1;  do_pass_param(&$1, ZEND_SEND_VAR, $$.u.constant.value.lval CLS_CC); }
+       |       '&' w_cvar                              {       $$.u.constant.value.lval = 1;  do_pass_param(&$2, ZEND_SEND_REF, $$.u.constant.value.lval CLS_CC); }
        |       non_empty_function_call_parameter_list ',' expr_without_variable        {       $$.u.constant.value.lval=$1.u.constant.value.lval+1;  do_pass_param(&$3, ZEND_SEND_VAL, $$.u.constant.value.lval CLS_CC); }
        |       non_empty_function_call_parameter_list ',' cvar                                         {       $$.u.constant.value.lval=$1.u.constant.value.lval+1;  do_pass_param(&$3, ZEND_SEND_VAR, $$.u.constant.value.lval CLS_CC); }
        |       non_empty_function_call_parameter_list ',' '&' w_cvar                           {       $$.u.constant.value.lval=$1.u.constant.value.lval+1;  do_pass_param(&$4, ZEND_SEND_REF, $$.u.constant.value.lval CLS_CC); }
@@ -343,7 +343,7 @@ expr_without_variable:
                ZEND_LIST '(' { do_list_init(); } assignment_list ')' '=' expr { do_list_end(&$$, &$7 CLS_CC); }
        |       w_cvar '=' expr         { do_assign(&$$, &$1, &$3 CLS_CC); }
        |       w_cvar '=' '&' w_cvar   { do_assign_ref(&$$, &$1, &$4 CLS_CC); }
-       |       w_cvar '=' NEW class_name { do_extended_fcall_begin(CLS_C); do_begin_new_object(&$2, &$1, &$3, &$4 CLS_CC); } ctor_arguments { do_end_new_object(&$4, &$3 CLS_CC); do_extended_fcall_end(CLS_C);  $$ = $2;}
+       |       w_cvar '=' NEW class_name { do_extended_fcall_begin(CLS_C); do_begin_new_object(&$2, &$1, &$3, &$4 CLS_CC); } ctor_arguments { do_end_new_object(&$4, &$3, &$6 CLS_CC); do_extended_fcall_end(CLS_C);  $$ = $2;}
        |       rw_cvar PLUS_EQUAL expr         { do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 CLS_CC); }
        |       rw_cvar MINUS_EQUAL expr        { do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 CLS_CC); }
        |       rw_cvar MUL_EQUAL expr          { do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 CLS_CC); }
@@ -391,13 +391,13 @@ expr_without_variable:
                expr     { do_qm_false(&$$, &$7, &$2, &$5 CLS_CC); }
        |       STRING  '(' { do_extended_fcall_begin(CLS_C); do_begin_function_call(&$1 CLS_CC); }
                                function_call_parameter_list
-                               ')' { do_end_function_call(&$1, &$$, 0 CLS_CC); do_extended_fcall_end(CLS_C); }
+                               ')' { do_end_function_call(&$1, &$$, &$4, 0 CLS_CC); do_extended_fcall_end(CLS_C); }
        |       r_cvar '(' { do_extended_fcall_begin(CLS_C); do_begin_dynamic_function_call(&$1 CLS_CC); } 
                                function_call_parameter_list 
-                               ')' { do_end_function_call(&$1, &$$, 0 CLS_CC); do_extended_fcall_end(CLS_C);}
+                               ')' { do_end_function_call(&$1, &$$, &$4, 0 CLS_CC); do_extended_fcall_end(CLS_C);}
        |       STRING T_PAAMAYIM_NEKUDOTAYIM STRING '(' { do_extended_fcall_begin(CLS_C); do_begin_class_member_function_call(&$1, &$3 CLS_CC); } 
                                                                                        function_call_parameter_list 
-                                                                                       ')' { do_end_function_call(&$3, &$$, 1 CLS_CC); do_extended_fcall_end(CLS_C);}
+                                                                                       ')' { do_end_function_call(&$3, &$$, &$6, 1 CLS_CC); do_extended_fcall_end(CLS_C);}
        |       internal_functions_in_yacc { $$ = $1; }
        |       INT_CAST expr           { do_cast(&$$, &$2, IS_LONG CLS_CC); }
        |       DOUBLE_CAST expr        { do_cast(&$$, &$2, IS_DOUBLE CLS_CC); }
@@ -421,8 +421,8 @@ exit_expr:
 
 
 ctor_arguments:
-               /* empty */
-       |       '(' function_call_parameter_list ')'
+               /* empty */                                                                     { $$.u.constant.value.lval=0; }
+       |       '(' function_call_parameter_list ')'            { $$ = $2; }
 ;
 
 
index c651c38e1c77cda6ac106b3ae967e1066757cb8a..716e8622995ccaee3f9fe2e82e0f5e2e862b7f56 100644 (file)
@@ -46,7 +46,7 @@
 #include "zend_llist.h"
 
 
-#define INTERNAL_FUNCTION_PARAMETERS HashTable *ht, zval *return_value, HashTable *list, HashTable *plist
+#define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, HashTable *list, HashTable *plist
 #define INTERNAL_FUNCTION_PARAM_PASSTHRU ht, return_value, list, plist
 
 /*
index 3dfea5f12102fee2de960a2eb1828c8ca70d672e..1b5040d6b0abd1c51b5440bf6dfaec4f4894169c 100644 (file)
@@ -31,21 +31,23 @@ static int module_count=0;
 HashTable list_destructors, module_registry;
 
 /* this function doesn't check for too many parameters */
-int getParameters(HashTable *ht, int param_count,...)
+int getParameters(int ht, int param_count,...)
 {
+       void **p = EG(argument_stack).elements+EG(argument_stack).top-1;
+       int arg_count = (ulong) *p;
        va_list ptr;
-       zval **param, **tmp = NULL, *param_ptr;
-       int i;
+       zval **param, *param_ptr;
+       ELS_FETCH();
+
+       if (param_count>arg_count) {
+               return FAILURE;
+       }
 
        va_start(ptr, param_count);
 
-       for (i = 0; i < param_count; i++) {
+       do {
                param = va_arg(ptr, zval **);
-               if (zend_hash_index_find(ht, i, (void **) &tmp) == FAILURE) {
-                       va_end(ptr);
-                       return FAILURE;
-               }
-               param_ptr = *tmp;
+               param_ptr = *(p-param_count);
                if (!param_ptr->is_ref && param_ptr->refcount>1) {
                        zval *new_tmp;
 
@@ -55,25 +57,30 @@ int getParameters(HashTable *ht, int param_count,...)
                        new_tmp->refcount = 1;
                        new_tmp->is_ref = 0;
                        param_ptr = new_tmp;
-                       zend_hash_index_update(ht, i, &param_ptr, sizeof(zval *), NULL);
+                       *(p-param_count) = param_ptr;
                }
                *param = param_ptr;
-       }
+       } while (--param_count);
        va_end(ptr);
+
        return SUCCESS;
 }
 
 
-int getParametersArray(HashTable *ht, int param_count, zval **argument_array)
+int getParametersArray(int ht, int param_count, zval **argument_array)
 {
-       int i;
-       zval **tmp = NULL, *param_ptr;
+       void **p = EG(argument_stack).elements+EG(argument_stack).top-1;
+       int arg_count = (ulong) *p;
+       zval *param_ptr;
+       ELS_FETCH();
 
-       for (i = 0; i < param_count; i++) {
-               if (zend_hash_index_find(ht, i, (void **) &tmp) == FAILURE) {
-                       return FAILURE;
-               }
-               param_ptr = *tmp;
+       if (param_count>arg_count) {
+               return FAILURE;
+       }
+
+
+       do {
+               param_ptr = *(p-param_count);
                if (!param_ptr->is_ref && param_ptr->refcount>1) {
                        zval *new_tmp;
 
@@ -83,10 +90,11 @@ int getParametersArray(HashTable *ht, int param_count, zval **argument_array)
                        new_tmp->refcount = 1;
                        new_tmp->is_ref = 0;
                        param_ptr = new_tmp;
-                       zend_hash_index_update(ht, i, &param_ptr, sizeof(zval *), NULL);
+                       *(p-param_count) = param_ptr;
                }
-               argument_array[i] = param_ptr;
-       }
+               *(argument_array++) = param_ptr;
+       } while (--param_count);
+
        return SUCCESS;
 }
 
@@ -106,14 +114,18 @@ int getThis(zval **this)
        return SUCCESS;
 }
 
-int ParameterPassedByReference(HashTable *ht, uint n)
+int ParameterPassedByReference(int ht, uint n)
 {
-       zval **tmp;
+       void **p = EG(argument_stack).elements+EG(argument_stack).top-1;
+       ulong arg_count = (ulong) *p;
+       zval *arg;
+       ELS_FETCH();
 
-       if (zend_hash_index_find(ht, n-1, (void **) &tmp) == FAILURE) {
-               return 0;
+       if (n>arg_count) {
+               return FAILURE;
        }
-       return (*tmp)->is_ref;
+       arg = (zval *) *(p-arg_count+n);
+       return arg->is_ref;
 }
 
 
index 2c95d0a41b8cc2235dc8a65f0673e1e33a7ff231..b2d6a4c81e91a253c337cef05ed1cb57a64f45f2 100644 (file)
 
 int zend_next_free_module(void);
 
-int getParameters(HashTable *ht, int param_count,...);
-int getParametersArray(HashTable *ht, int param_count, zval **argument_array);
+int getParameters(int ht, int param_count,...);
+int getParametersArray(int ht, int param_count, zval **argument_array);
 int getThis(zval **this);
-int ParameterPassedByReference(HashTable *ht, uint n);
+int ParameterPassedByReference(int ht, uint n);
 int register_functions(function_entry *functions);
 void unregister_functions(function_entry *functions, int count);
 int register_module(zend_module_entry *module_entry);
@@ -36,7 +36,7 @@ ZEND_API void wrong_param_count(void);
 
 #define WRONG_PARAM_COUNT { wrong_param_count(); return; }
 #define WRONG_PARAM_COUNT_WITH_RETVAL(ret) { wrong_param_count(); return ret; }
-#define ARG_COUNT(ht) (ht->nNextFreeElement)
+#define ARG_COUNT(ht) (ht)
 
 #define BYREF_NONE 0
 #define BYREF_FORCE 1
index f661beb3080a3edbbe5a27feb8e99b2583051d5d..f29c33f02405e13d549e470578dc1b2a1f98ebd7 100644 (file)
@@ -702,7 +702,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);
@@ -741,7 +740,7 @@ void do_begin_class_member_function_call(znode *class_name, znode *function_name
 }
 
 
-void do_end_function_call(znode *function_name, znode *result, int is_method CLS_DC)
+void do_end_function_call(znode *function_name, znode *result, znode *argument_list, int is_method CLS_DC)
 {
        zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
        ELS_FETCH();
@@ -754,6 +753,7 @@ void do_end_function_call(znode *function_name, znode *result, int is_method CLS
        SET_UNUSED(opline->op2);
        opline->op2.u.constant.value.lval = is_method;
        zend_stack_del_top(&CG(function_call_stack));
+       opline->extended_value = argument_list->u.constant.value.lval;
 }
 
 
@@ -777,8 +777,8 @@ void do_pass_param(znode *param, int op, int offset CLS_DC)
                                break;
                }
        }
-       if (arg_types && offset<arg_types[0]
-               && arg_types[1+offset]==BYREF_FORCE) {
+       if (arg_types && offset<=arg_types[0]
+               && arg_types[offset]==BYREF_FORCE) {
                /* change to passing by reference */
                switch (param->op_type) {
                        case IS_VAR:
@@ -1223,14 +1223,14 @@ void do_begin_new_object(znode *result, znode *variable, znode *new_token, znode
 }
 
 
-void do_end_new_object(znode *class_name, znode *new_token CLS_DC)
+void do_end_new_object(znode *class_name, znode *new_token, znode *argument_list CLS_DC)
 {
        znode ctor_result;
 
        if (class_name->op_type == IS_CONST) {
                zval_copy_ctor(&class_name->u.constant);
        }
-       do_end_function_call(class_name, &ctor_result, 1 CLS_CC);
+       do_end_function_call(class_name, &ctor_result, argument_list, 1 CLS_CC);
        do_free(&ctor_result CLS_CC);
 
        CG(active_op_array)->opcodes[new_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
@@ -1438,7 +1438,7 @@ void do_list_end(znode *result, znode *expr CLS_DC)
        le = CG(list_llist).head;
        while (le) {
                do_assign(result, &((list_llist_element *) le->data)->var, &((list_llist_element *) le->data)->value CLS_CC);
-               EG(active_op_array)->opcodes[EG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
+               CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
                le = le->next;
        }
        zend_llist_destroy(&CG(dimension_llist));
index c54f7d4705d3ff72a25d179168a9d3d8b7e697f1..ff66074cd5c125bd80e34b1be72d276adba38c63 100644 (file)
@@ -62,6 +62,7 @@ typedef struct _zend_op {
        znode result;
        znode op1;
        znode op2;
+       ulong extended_value;
        char *filename;
        uint lineno;
 } zend_op;
@@ -238,7 +239,7 @@ void do_receive_arg(int op, znode *var, znode *offset, znode *initialization, un
 void do_begin_function_call(znode *function_name CLS_DC);
 void do_begin_dynamic_function_call(znode *function_name CLS_DC);
 void do_begin_class_member_function_call(znode *class_name, znode *function_name CLS_DC);
-void do_end_function_call(znode *function_name, znode *result, int is_method CLS_DC);
+void do_end_function_call(znode *function_name, znode *result, znode *argument_list, int is_method CLS_DC);
 void do_return(znode *expr CLS_DC);
 
 void do_pass_param(znode *param, int op, int offset CLS_DC);
@@ -269,7 +270,7 @@ void do_pop_object(znode *object CLS_DC);
 
 
 void do_begin_new_object(znode *result, znode *variable, znode *new_token, znode *class_name CLS_DC);
-void do_end_new_object(znode *class_name, znode *new_token CLS_DC);
+void do_end_new_object(znode *class_name, znode *new_token, znode *argument_list CLS_DC);
 
 void do_fetch_constant(znode *result, znode *constant_name, int mode CLS_DC);
 
index 01b19c3c1de4ec4d5caa8c230a41ea641ff37aeb..bf868a04ae8df526e1061338ed7026821ee80db9 100644 (file)
@@ -62,7 +62,7 @@ static void destroy_garbage(HashTable *ht)
 /* Prototypes */
 static zval get_overloaded_property(ELS_D);
 static void set_overloaded_property(zval *value ELS_DC);
-static void call_overloaded_function(HashTable *ht, zval *return_value, HashTable *list, HashTable *plist ELS_DC);
+static void call_overloaded_function(int arg_count, zval *return_value, HashTable *list, HashTable *plist ELS_DC);
 static inline void zend_fetch_var_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type ELS_DC);
 static inline void zend_fetch_dimension_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type ELS_DC);
 static inline void zend_fetch_property_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type ELS_DC);
@@ -800,12 +800,12 @@ static void set_overloaded_property(zval *value ELS_DC)
 }
 
 
-static void call_overloaded_function(HashTable *ht, zval *return_value, HashTable *list, HashTable *plist ELS_DC)
+static void call_overloaded_function(int arg_count, zval *return_value, HashTable *list, HashTable *plist ELS_DC)
 {
        zend_property_reference *property_reference;
 
        zend_stack_top(&EG(overloaded_objects_stack), (void **) &property_reference);
-       (*(property_reference->object))->value.obj.ce->handle_function_call(ht, return_value, list, plist, property_reference);
+       (*(property_reference->object))->value.obj.ce->handle_function_call(arg_count, return_value, list, plist, property_reference);
        //(*(property_reference->object))->value.obj.ce->handle_function_call(NULL, NULL, NULL, NULL, NULL);
        zend_llist_destroy(&property_reference->elements_list);
 
@@ -1313,15 +1313,7 @@ overloaded_function_call_cont:
                                object_ptr=NULL;
                                function_being_called=NULL;
 init_by_name_cont:
-                               zend_ptr_stack_push(&EG(function_symbol_table_stack), function_state.function_symbol_table);
-                               if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
-                                       //printf("Cache hit!  Reusing %x\n", symtable_cache[symtable_cache_ptr]);
-                                       function_state.function_symbol_table = *(EG(symtable_cache_ptr)--);
-                               } else {
-                                       function_state.function_symbol_table = (HashTable *) emalloc(sizeof(HashTable));
-                                       zend_hash_init(function_state.function_symbol_table, 0, NULL, PVAL_PTR_DTOR, 0);
-                                       //printf("Cache miss!  Initialized %x\n", function_state.function_symbol_table);
-                               }
+#if 0
                                if (object_ptr && function_being_called && function_being_called->type!=ZEND_OVERLOADED_FUNCTION) {
                                        zval *dummy = (zval *) emalloc(sizeof(zval)), **this_ptr;
 
@@ -1332,6 +1324,7 @@ init_by_name_cont:
                                        zend_assign_to_variable_reference(NULL, this_ptr, object_ptr, NULL ELS_CC);
                                        object_ptr = NULL;
                                }
+#endif
                                break;
                        case ZEND_DO_FCALL: 
                                if (function_being_called) {
@@ -1351,11 +1344,20 @@ init_by_name_cont:
                                                function_being_called = zend_ptr_stack_pop(&EG(arg_types_stack));
                                        }
                                        calling_symbol_table = EG(active_symbol_table);
-                                       EG(active_symbol_table) = function_state.function_symbol_table;
+                                       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);
-                                               ((zend_internal_function *) function_state.function)->handler(EG(active_symbol_table), &Ts[opline->result.u.var].tmp_var, &EG(regular_list), &EG(persistent_list));
+                                               ((zend_internal_function *) function_state.function)->handler(opline->extended_value, &Ts[opline->result.u.var].tmp_var, &EG(regular_list), &EG(persistent_list));
                                        } else if (function_state.function->type==ZEND_USER_FUNCTION) {
+                                               if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
+                                                       //printf("Cache hit!  Reusing %x\n", symtable_cache[symtable_cache_ptr]);
+                                                       function_state.function_symbol_table = *(EG(symtable_cache_ptr)--);
+                                               } else {
+                                                       function_state.function_symbol_table = (HashTable *) emalloc(sizeof(HashTable));
+                                                       zend_hash_init(function_state.function_symbol_table, 0, NULL, PVAL_PTR_DTOR, 0);
+                                                       //printf("Cache miss!  Initialized %x\n", function_state.function_symbol_table);
+                                               }
+                                               EG(active_symbol_table) = function_state.function_symbol_table;
                                                original_return_value = EG(return_value);
                                                EG(return_value) = &Ts[opline->result.u.var].tmp_var;
                                                var_uninit(EG(return_value));
@@ -1364,21 +1366,21 @@ init_by_name_cont:
                                                EG(opline_ptr) = &opline;
                                                EG(active_op_array) = op_array;
                                                EG(return_value)=original_return_value;
+                                               if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) {
+                                                       zend_hash_destroy(function_state.function_symbol_table);
+                                                       efree(function_state.function_symbol_table);
+                                               } else {
+                                                       *(++EG(symtable_cache_ptr)) = function_state.function_symbol_table;
+                                                       zend_hash_clean(*EG(symtable_cache_ptr));
+                                               }
                                        } else { /* ZEND_OVERLOADED_FUNCTION */
-                                               call_overloaded_function(EG(active_symbol_table), &Ts[opline->result.u.var].tmp_var, &EG(regular_list), &EG(persistent_list));
+                                               call_overloaded_function(opline->extended_value, &Ts[opline->result.u.var].tmp_var, &EG(regular_list), &EG(persistent_list));
                                                efree(function_being_called);
                                        }
                                        function_state.function = (zend_function *) op_array;
                                        EG(active_symbol_table) = calling_symbol_table;
-                                       if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) {
-                                               zend_hash_destroy(function_state.function_symbol_table);
-                                               efree(function_state.function_symbol_table);
-                                       } else {
-                                               *(++EG(symtable_cache_ptr)) = function_state.function_symbol_table;
-                                               zend_hash_clean(*EG(symtable_cache_ptr));
-                                       }
                                        EG(function_state_ptr) = &function_state;
-                                       function_state.function_symbol_table = zend_ptr_stack_pop(&EG(function_symbol_table_stack));
+                                       zend_ptr_stack_clear_multiple(ELS_C);
                                }
                                break;
                        case ZEND_RETURN: {
@@ -1400,8 +1402,8 @@ init_by_name_cont:
                        case ZEND_SEND_VAL: 
                                if (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[1+opline->op2.u.opline_num]==BYREF_FORCE) {
+                                       && 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) {
                                                zend_error(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num);
                                }
                                {
@@ -1410,7 +1412,8 @@ init_by_name_cont:
                                        *valptr = Ts[opline->op1.u.var].tmp_var;
                                        valptr->refcount=1;
                                        valptr->is_ref=0;
-                                       zend_hash_next_index_insert_ptr(function_state.function_symbol_table, valptr, sizeof(zval *), NULL);
+                                       //zend_hash_next_index_insert_ptr(function_state.function_symbol_table, valptr, sizeof(zval *), NULL);
+                                       zend_ptr_stack_push(&EG(argument_stack), valptr);
                                }
                                break;
                        case ZEND_SEND_VAR:
@@ -1438,7 +1441,8 @@ init_by_name_cont:
                                                zval_copy_ctor(varptr);
                                        }
                                        varptr->refcount++;
-                                       zend_hash_next_index_insert_ptr(function_state.function_symbol_table, varptr, sizeof(zval *), NULL);
+                                       //zend_hash_next_index_insert_ptr(function_state.function_symbol_table, varptr, sizeof(zval *), NULL);
+                                       zend_ptr_stack_push(&EG(argument_stack), varptr);
                                }
                                break;
 send_by_ref:
@@ -1459,13 +1463,15 @@ send_by_ref:
                                                /* at the end of this code refcount is always 1 */
                                        }
                                        varptr->refcount++;
-                                       zend_hash_next_index_insert_ptr(function_state.function_symbol_table, varptr, sizeof(zval *), NULL);
+                                       //zend_hash_next_index_insert_ptr(function_state.function_symbol_table, varptr, sizeof(zval *), NULL);
+                                       zend_ptr_stack_push(&EG(argument_stack), varptr);
                                }
                                break;
                        case ZEND_RECV: {
                                        zval **param;
 
-                                       if (zend_hash_index_find(EG(active_symbol_table), opline->op1.u.constant.value.lval, (void **) &param)==FAILURE) {
+                                       //if (zend_hash_index_find(EG(active_symbol_table), opline->op1.u.constant.value.lval, (void **) &param)==FAILURE) {
+                                       if (zend_ptr_stack_get_arg(opline->op1.u.constant.value.lval, (void **) &param)==FAILURE) {
                                                zend_error(E_NOTICE, "Missing argument %d for %s()\n", opline->op1.u.constant.value.lval, get_active_function_name());
                                        } else if ((*param)->is_ref) {
                                                zend_assign_to_variable_reference(NULL, get_zval_ptr_ptr(&opline->result, Ts, BP_VAR_W), param, NULL ELS_CC);
@@ -1477,7 +1483,8 @@ send_by_ref:
                        case ZEND_RECV_INIT: {
                                        zval **param, *assignment_value;
 
-                                       if (zend_hash_index_find(EG(active_symbol_table), opline->op1.u.constant.value.lval, (void **) &param)==FAILURE) {
+                                       //if (zend_hash_index_find(EG(active_symbol_table), opline->op1.u.constant.value.lval, (void **) &param)==FAILURE) {
+                                       if (zend_ptr_stack_get_arg(opline->op1.u.constant.value.lval, (void **) &param)==FAILURE) {
                                                if (opline->op2.u.constant.type == IS_CONSTANT) {
                                                        zval *default_value = (zval *) emalloc(sizeof(zval));
                                                        zval tmp;
index d09d42caaa56b00821775431c96e2afbc8b6197f..206bcd6f6f70dea74857c4bac513dbc52e7b4863 100644 (file)
@@ -45,6 +45,10 @@ ZEND_API inline int i_zend_is_true(zval *op);
 ZEND_API void zval_update_constant(zval *p);
 ZEND_API inline void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, zval **value_ptr_ptr, temp_variable *Ts ELS_DC);
 
+/* dedicated Zend executor functions - do not use! */
+ZEND_API inline void zend_ptr_stack_clear_multiple(ELS_D);
+ZEND_API inline int zend_ptr_stack_get_arg(int requested_arg, void **data);
+
 #if SUPPORT_INTERACTIVE
 void execute_new_code(CLS_D);
 #endif
index ca0157e28fdab01a5a2fb44f9ec973378ff7f995..1600be6e542f72f26bb4052ea9f9a31b781f51cf 100644 (file)
@@ -86,6 +86,8 @@ void init_executor(CLS_D ELS_DC)
        EG(function_table) = CG(function_table);
        EG(class_table) = CG(class_table);
 
+       zend_ptr_stack_init(&EG(argument_stack));
+
        EG(AiCount) = 0;
        zend_ptr_stack_init(&EG(garbage));
 
@@ -124,6 +126,7 @@ void shutdown_executor(ELS_D)
 
        zend_hash_destroy(&EG(symbol_table));
 
+       zend_ptr_stack_destroy(&EG(argument_stack));
        if (EG(main_op_array)) {
                destroy_op_array(EG(main_op_array));
                efree(EG(main_op_array));
@@ -287,7 +290,8 @@ int call_user_function(HashTable *function_table, zval *object, zval *function_n
                param->refcount=1;
                param->is_ref=0;
                zval_copy_ctor(param);
-               zend_hash_next_index_insert_ptr(function_state.function_symbol_table, param, sizeof(zval *), NULL);
+               //zend_hash_next_index_insert_ptr(function_state.function_symbol_table, param, sizeof(zval *), NULL);
+               zend_ptr_stack_push(&EG(argument_stack), param);
        }
 
        if (object) {
@@ -314,7 +318,7 @@ int call_user_function(HashTable *function_table, zval *object, zval *function_n
                EG(return_value)=original_return_value;
                EG(opline_ptr) = original_opline_ptr;
        } else {
-               ((zend_internal_function *) function_state.function)->handler(EG(active_symbol_table), retval, &EG(regular_list), &EG(persistent_list));
+               ((zend_internal_function *) function_state.function)->handler(param_count, retval, &EG(regular_list), &EG(persistent_list));
        }
        zend_hash_destroy(EG(active_symbol_table));
        efree(EG(active_symbol_table));
@@ -443,3 +447,34 @@ void execute_new_code(CLS_D)
        CG(active_op_array)->start_op_number = CG(active_op_array)->last_executed_op_number;
 }
 #endif
+
+
+/* these are a dedicated, optimized, function, and shouldn't be used for any purpose
+ * other than by Zend's executor
+ */
+ZEND_API inline void zend_ptr_stack_clear_multiple(ELS_D)
+{
+       void **p = EG(argument_stack).top_element-1;
+       int delete_count = (ulong) *p;
+
+       EG(argument_stack).top -= (delete_count+1);
+       while (--delete_count>=0) {
+               zval_ptr_dtor((zval **) --p);
+       }
+       EG(argument_stack).top_element = p;
+}
+
+
+
+ZEND_API int zend_ptr_stack_get_arg(int requested_arg, void **data)
+{
+       void **p = EG(argument_stack).elements+EG(argument_stack).top-1;
+       int arg_count = (ulong) *p;
+
+       if (requested_arg>arg_count) {
+               return FAILURE;
+       }
+       *data = (p-arg_count+requested_arg-1);
+       return SUCCESS;
+}
+
index f20a7f5e6ef3e721dd810685eac96bc79d013a46..329e1844938e5b567732dfb3c7d90a6e1122cb6d 100644 (file)
@@ -186,6 +186,8 @@ struct _zend_executor_globals {
        HashTable regular_list;
        HashTable persistent_list;
 
+       zend_ptr_stack argument_stack;
+
 #if SUPPORT_INTERACTIVE
        int interactive;
 #endif
index 3eeec0576ca5ab138ca47ca2e2dc4630fe9f7afa..db83c2bd3f924bb5ad32ced323379425c403b3d7 100644 (file)
@@ -69,3 +69,5 @@ ZEND_API void zend_ptr_stack_clean(zend_ptr_stack *stack, void (*func)(void *))
        zend_ptr_stack_apply(stack, func);
        stack->top = 0;
 }
+
+