Browse Source

This patch is a go. Not fully optimized yet, but working properly.

Prepatch tagged as BEFORE_STACK_PATCH.
migration/INITIAL
Zeev Suraski 28 years ago
parent
commit
39a7f4c306
  1. 30
      Zend/zend-parser.y
  2. 2
      Zend/zend.h
  3. 66
      Zend/zend_API.c
  4. 8
      Zend/zend_API.h
  5. 14
      Zend/zend_compile.c
  6. 5
      Zend/zend_compile.h
  7. 67
      Zend/zend_execute.c
  8. 4
      Zend/zend_execute.h
  9. 39
      Zend/zend_execute_API.c
  10. 2
      Zend/zend_globals.h
  11. 2
      Zend/zend_ptr_stack.c

30
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; }
;

2
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
/*

66
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, &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;
}

8
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

14
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));

5
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);

67
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 **) &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;

4
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

39
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;
}

2
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

2
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;
}
Loading…
Cancel
Save