diff options
author | Zeev Suraski <zeev@php.net> | 1999-04-12 18:29:09 +0000 |
---|---|---|
committer | Zeev Suraski <zeev@php.net> | 1999-04-12 18:29:09 +0000 |
commit | 39a7f4c306675d3a03ff56f0a8c7f5e2183ab09a (patch) | |
tree | f91348978d003d8e668279dbab8bba7646965902 /Zend | |
parent | b06c5731fc2ac9ee11600096061e67b68a5b713e (diff) | |
download | php-git-39a7f4c306675d3a03ff56f0a8c7f5e2183ab09a.tar.gz |
This patch is a go. Not fully optimized yet, but working properly.
Prepatch tagged as BEFORE_STACK_PATCH.
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/zend-parser.y | 30 | ||||
-rw-r--r-- | Zend/zend.h | 2 | ||||
-rw-r--r-- | Zend/zend_API.c | 66 | ||||
-rw-r--r-- | Zend/zend_API.h | 8 | ||||
-rw-r--r-- | Zend/zend_compile.c | 14 | ||||
-rw-r--r-- | Zend/zend_compile.h | 5 | ||||
-rw-r--r-- | Zend/zend_execute.c | 67 | ||||
-rw-r--r-- | Zend/zend_execute.h | 4 | ||||
-rw-r--r-- | Zend/zend_execute_API.c | 39 | ||||
-rw-r--r-- | Zend/zend_globals.h | 2 | ||||
-rw-r--r-- | Zend/zend_ptr_stack.c | 2 |
11 files changed, 151 insertions, 88 deletions
diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y index a3f22364ab..1fab94d93d 100644 --- a/Zend/zend-parser.y +++ b/Zend/zend-parser.y @@ -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; } ; diff --git a/Zend/zend.h b/Zend/zend.h index c651c38e1c..716e862299 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -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 /* diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 3dfea5f121..1b5040d6b0 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -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, ¶m_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, ¶m_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; } diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 2c95d0a41b..b2d6a4c81e 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -23,10 +23,10 @@ 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 diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f661beb308..f29c33f024 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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)); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index c54f7d4705..ff66074cd5 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 01b19c3c1d..bf868a04ae 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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 **) ¶m)==FAILURE) { + //if (zend_hash_index_find(EG(active_symbol_table), opline->op1.u.constant.value.lval, (void **) ¶m)==FAILURE) { + if (zend_ptr_stack_get_arg(opline->op1.u.constant.value.lval, (void **) ¶m)==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 **) ¶m)==FAILURE) { + //if (zend_hash_index_find(EG(active_symbol_table), opline->op1.u.constant.value.lval, (void **) ¶m)==FAILURE) { + if (zend_ptr_stack_get_arg(opline->op1.u.constant.value.lval, (void **) ¶m)==FAILURE) { if (opline->op2.u.constant.type == IS_CONSTANT) { zval *default_value = (zval *) emalloc(sizeof(zval)); zval tmp; diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index d09d42caaa..206bcd6f6f 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -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 diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index ca0157e28f..1600be6e54 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -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; +} + diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index f20a7f5e6e..329e184493 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -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 diff --git a/Zend/zend_ptr_stack.c b/Zend/zend_ptr_stack.c index 3eeec0576c..db83c2bd3f 100644 --- a/Zend/zend_ptr_stack.c +++ b/Zend/zend_ptr_stack.c @@ -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; } + + |