Browse Source

- God damn this sucked. I hopefully fixed the problems with classes although

we might need to clean stuff up a bit.
experimetnal/RETURN_REF_PATCH
Andi Gutmans 27 years ago
parent
commit
37159e7863
  1. 127
      Zend/zend_execute.c

127
Zend/zend_execute.c

@ -74,7 +74,26 @@ static void zend_extension_fcall_end_handler(zend_extension *extension, zend_op_
&& function_being_called->common.arg_types \
&& offset<=function_being_called->common.arg_types[0] \
&& function_being_called->common.arg_types[offset]==BYREF_FORCE)
#define MAKE_REF_ON_READ_OBJECT(s) \
{ \
zval **ptr_ptr; \
\
if ((ptr_ptr = (s)) \
&& ((*ptr_ptr)->type == IS_OBJECT) \
&& (!(*ptr_ptr)->value.obj.ce->handle_function_call) \
&& (!(*ptr_ptr)->is_ref) \
&& ((*ptr_ptr)->refcount>2)) { /* 2 because it's also locked */ \
zval *ptr = *ptr_ptr; \
\
ptr->refcount -= 2; \
*(ptr_ptr) = (zval *) emalloc(sizeof(zval)); \
**(ptr_ptr) = *ptr; \
zval_copy_ctor(*(ptr_ptr)); \
(*(ptr_ptr))->refcount=2; \
(*(ptr_ptr))->is_ref = 1; \
} \
}
static inline zval *_get_zval_ptr(znode *node, temp_variable *Ts, int *should_free ELS_DC)
{
@ -139,6 +158,35 @@ static inline zval *_get_zval_ptr(znode *node, temp_variable *Ts, int *should_fr
return NULL;
}
static inline zval *_get_object_zval_ptr(znode *node, temp_variable *Ts, int *should_free ELS_DC)
{
switch(node->op_type) {
case IS_TMP_VAR:
*should_free = 1;
return &Ts[node->u.var].tmp_var;
break;
case IS_VAR:
if (Ts[node->u.var].var.ptr) {
PZVAL_UNLOCK(Ts[node->u.var].var.ptr);
*should_free = 0;
return Ts[node->u.var].var.ptr;
} else {
*should_free = 1;
return NULL;
}
break;
case IS_UNUSED:
return NULL;
break;
#if DEBUG_ZEND
default:
zend_error(E_ERROR, "Unknown temporary variable type");
break;
#endif
}
return NULL;
}
static inline zval **_get_zval_ptr_ptr(znode *node, temp_variable *Ts ELS_DC)
{
@ -155,40 +203,6 @@ static inline zval **_get_zval_ptr_ptr(znode *node, temp_variable *Ts ELS_DC)
}
}
static inline zval *_get_object_zval_ptr(znode *node, temp_variable *Ts, int *should_free, zval ***object_ptr_ptr ELS_DC)
{
switch(node->op_type) {
case IS_TMP_VAR:
*should_free = 1;
*object_ptr_ptr = NULL;
return &Ts[node->u.var].tmp_var;
break;
case IS_VAR:
if (Ts[node->u.var].var.ptr_ptr) {
PZVAL_UNLOCK(*Ts[node->u.var].var.ptr_ptr);
*should_free = 0;
*object_ptr_ptr = Ts[node->u.var].var.ptr_ptr;
return **object_ptr_ptr;
} else {
*should_free = 1;
*object_ptr_ptr = NULL;
return NULL;
}
break;
case IS_UNUSED:
*object_ptr_ptr = NULL;
return NULL;
break;
#if DEBUG_ZEND
default:
zend_error(E_ERROR, "Unknown temporary variable type");
break;
#endif
}
return NULL;
}
static inline zval **zend_fetch_property_address_inner(HashTable *ht, znode *op2, temp_variable *Ts, int type ELS_DC)
{
int free_op2;
@ -896,7 +910,6 @@ static void call_overloaded_function(int arg_count, zval *return_value, HashTabl
typedef struct _object_info {
zval *ptr;
zval **ptr_ptr;
} object_info;
void execute(zend_op_array *op_array ELS_DC)
@ -905,7 +918,7 @@ void execute(zend_op_array *op_array ELS_DC)
zend_op *end = op_array->opcodes + op_array->last;
zend_function_state function_state;
zend_function *function_being_called=NULL;
object_info object = {NULL, NULL};
object_info object = {NULL};
#if !defined (__GNUC__) || __GNUC__ < 2
temp_variable *Ts = (temp_variable *) do_alloca(sizeof(temp_variable)*op_array->T);
#else
@ -1132,6 +1145,7 @@ binary_assign_op_addr: {
break;
case ZEND_FETCH_R:
zend_fetch_var_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_R ELS_CC);
MAKE_REF_ON_READ_OBJECT(Ts[opline->result.u.var].var.ptr_ptr);
AI_USE_PTR(Ts[opline->result.u.var].var);
break;
case ZEND_FETCH_W:
@ -1159,6 +1173,7 @@ binary_assign_op_addr: {
PZVAL_LOCK(*Ts[opline->op1.u.var].var.ptr_ptr);
}
zend_fetch_dimension_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_R ELS_CC);
MAKE_REF_ON_READ_OBJECT(Ts[opline->result.u.var].var.ptr_ptr);
AI_USE_PTR(Ts[opline->result.u.var].var);
break;
case ZEND_FETCH_DIM_W:
@ -1183,6 +1198,7 @@ binary_assign_op_addr: {
break;
case ZEND_FETCH_OBJ_R:
zend_fetch_property_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_R ELS_CC);
MAKE_REF_ON_READ_OBJECT(Ts[opline->result.u.var].var.ptr_ptr);
AI_USE_PTR(Ts[opline->result.u.var].var);
break;
case ZEND_FETCH_OBJ_W:
@ -1360,12 +1376,7 @@ binary_assign_op_addr: {
HashTable *active_function_table;
zval tmp;
zend_ptr_stack_n_push(&EG(arg_types_stack), 3, function_being_called, object.ptr, object.ptr_ptr);
/*
zend_ptr_stack_push(&EG(arg_types_stack), function_being_called);
zend_ptr_stack_push(&EG(arg_types_stack), object.ptr);
zend_ptr_stack_push(&EG(arg_types_stack), object.ptr_ptr);
*/
zend_ptr_stack_n_push(&EG(arg_types_stack), 2, function_being_called, object.ptr);
if (opline->extended_value & ZEND_CTOR_CALL) {
/* constructor call */
@ -1396,12 +1407,14 @@ binary_assign_op_addr: {
if (zend_hash_find(EG(active_symbol_table), "this", sizeof("this"), (void **) &object_ptr_ptr)==FAILURE) {
object.ptr=NULL;
} else {
/* We assume that "this" is already is_ref and pointing to the object.
If it isn't then tough */
object.ptr = *object_ptr_ptr;
object.ptr_ptr = object_ptr_ptr;
object.ptr->refcount++; /* For this pointer */
}
} else { /* used for member function calls */
object.ptr = _get_object_zval_ptr(&opline->op1, Ts, &EG(free_op1), &object.ptr_ptr ELS_CC);
object.ptr = _get_object_zval_ptr(&opline->op1, Ts, &EG(free_op1) ELS_CC);
if (!object.ptr
|| ((object.ptr->type==IS_OBJECT) && (object.ptr->value.obj.ce->handle_function_call))) { /* overloaded function call */
zend_overloaded_element overloaded_element;
@ -1429,6 +1442,7 @@ binary_assign_op_addr: {
if (object.ptr->type != IS_OBJECT) {
zend_error(E_ERROR, "Call to a member function on a non-object");
}
object.ptr->refcount++; /* For this pointer */
active_function_table = &(object.ptr->value.obj.ce->function_table);
}
} else { /* function pointer */
@ -1481,24 +1495,12 @@ do_fcall_common:
&& object.ptr
&& function_being_called->type!=ZEND_OVERLOADED_FUNCTION) {
zval **this_ptr;
zval *tmp;
zend_hash_update_ptr(function_state.function_symbol_table, "this", sizeof("this"), NULL, sizeof(zval *), (void **) &this_ptr);
if (!PZVAL_IS_REF(object.ptr)) {
/* break it away */
object.ptr->refcount--;
if (object.ptr->refcount>0) {
tmp = (zval *) emalloc(sizeof(zval));
*tmp = *object.ptr;
zendi_zval_copy_ctor(*tmp);
object.ptr = tmp;
*object.ptr_ptr = tmp;
}
object.ptr->refcount = 1;
object.ptr->is_ref = 1;
zend_error(E_WARNING,"Problem with method call. Report this bug\n");
}
*this_ptr = object.ptr;
object.ptr->refcount++;
object.ptr = NULL;
}
original_return_value = EG(return_value);
@ -1522,12 +1524,7 @@ do_fcall_common:
efree(function_being_called);
}
if (opline->opcode == ZEND_DO_FCALL_BY_NAME) {
zend_ptr_stack_n_pop(&EG(arg_types_stack), 3, &object.ptr_ptr, &object.ptr, &function_being_called);
/*
object.ptr_ptr = zend_ptr_stack_pop(&EG(arg_types_stack));
object.ptr = zend_ptr_stack_pop(&EG(arg_types_stack));
function_being_called = zend_ptr_stack_pop(&EG(arg_types_stack));
*/
zend_ptr_stack_n_pop(&EG(arg_types_stack), 2, &object.ptr, &function_being_called);
}
function_state.function = (zend_function *) op_array;
EG(function_state_ptr) = &function_state;

Loading…
Cancel
Save