last_op->opcode = ZEND_INIT_METHOD_CALL;
- if (last_op->op2.op_type == IS_UNUSED && last_op->op2.u.EA.type == ZEND_FETCH_FROM_THIS) {
- last_op->op2 = last_op->op1;
- memset(&last_op->op1, 0, sizeof(znode));
- SET_UNUSED(last_op->op1);
- last_op->extended_value = ZEND_FETCH_FROM_THIS;
- }
-
left_bracket->u.constant.value.lval = ZEND_INIT_FCALL_BY_NAME;
zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
(opline_ptr->op1.u.constant.value.str.len == (sizeof("this")-1)) &&
!memcmp(opline_ptr->op1.u.constant.value.str.val, "this", sizeof("this"))) {
efree(opline_ptr->op1.u.constant.value.str.val);
- opline_ptr->op1 = *property;
- SET_UNUSED(opline_ptr->op2);
- opline_ptr->op2.u.EA.type = ZEND_FETCH_FROM_THIS;
+ SET_UNUSED(opline_ptr->op1); /* this means $this for objects */
+ opline_ptr->op2 = *property;
+ /* if it was usual fetch, we change it to object fetch */
+ switch(opline_ptr->opcode) {
+ case ZEND_FETCH_W:
+ opline_ptr->opcode = ZEND_FETCH_OBJ_W;
+ break;
+ case ZEND_FETCH_R:
+ opline_ptr->opcode = ZEND_FETCH_OBJ_R;
+ break;
+ case ZEND_FETCH_RW:
+ opline_ptr->opcode = ZEND_FETCH_OBJ_RW;
+ break;
+ case ZEND_FETCH_IS:
+ opline_ptr->opcode = ZEND_FETCH_OBJ_IS;
+ break;
+ case ZEND_FETCH_UNSET:
+ opline_ptr->opcode = ZEND_FETCH_OBJ_UNSET;
+ break;
+ case ZEND_FETCH_FUNC_ARG:
+ opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG;
+ break;
+ }
if (CG(active_class_entry) && (opline_ptr->op1.op_type == IS_CONST)) {
if (zend_hash_exists(&CG(active_class_entry)->private_properties, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len+1)) {
char *priv_name;
int priv_name_length;
- mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len);
+ mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len);
- STR_FREE(opline_ptr->op1.u.constant.value.str.val);
- opline_ptr->op1.u.constant.value.str.val = priv_name;
- opline_ptr->op1.u.constant.value.str.len = priv_name_length;
- } else if (zend_hash_exists(&CG(active_class_entry)->protected_properties, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len+1)) {
+ STR_FREE(opline_ptr->op2.u.constant.value.str.val);
+ opline_ptr->op2.u.constant.value.str.val = priv_name;
+ opline_ptr->op2.u.constant.value.str.len = priv_name_length;
+ } else if (zend_hash_exists(&CG(active_class_entry)->protected_properties, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len+1)) {
char *prot_name;
int prot_name_length;
- mangle_property_name(&prot_name, &prot_name_length, "*", 1, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len);
+ mangle_property_name(&prot_name, &prot_name_length, "*", 1, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len);
- STR_FREE(opline_ptr->op1.u.constant.value.str.val);
- opline_ptr->op1.u.constant.value.str.val = prot_name;
- opline_ptr->op1.u.constant.value.str.len = prot_name_length;
+ STR_FREE(opline_ptr->op2.u.constant.value.str.val);
+ opline_ptr->op2.u.constant.value.str.val = prot_name;
+ opline_ptr->op2.u.constant.value.str.len = prot_name_length;
}
}
*result = opline_ptr->result;
static inline void make_real_object(zval **object_ptr TSRMLS_DC)
{
+/* this should modify object only if it's empty */
if ((*object_ptr)->type == IS_NULL
|| ((*object_ptr)->type == IS_BOOL && (*object_ptr)->value.lval==0)
|| ((*object_ptr)->type == IS_STRING && (*object_ptr)->value.str.len == 0)) {
object_init(*object_ptr);
}
}
-
+
+static inline zval **get_obj_zval_ptr_ptr(znode *op, temp_variable *Ts, int type TSRMLS_DC)
+{
+ if(op->op_type == IS_UNUSED) {
+ if(EG(This)) {
+ /* this should actually never be modified, _ptr_ptr is modified only when
+ the object is empty */
+ return &EG(This);
+ } else {
+ zend_error(E_ERROR, "Using $this when not in object context");
+ }
+ }
+ return get_zval_ptr_ptr(op, Ts, type);
+}
+
+static inline zval *get_obj_zval_ptr(znode *op, temp_variable *Ts, int *freeop, int type TSRMLS_DC)
+{
+ if(op->op_type == IS_UNUSED) {
+ if(EG(This)) {
+ return EG(This);
+ } else {
+ zend_error(E_ERROR, "Using $this when not in object context");
+ }
+ }
+ return get_zval_ptr(op, Ts, freeop, type);
+}
+
static inline void zend_assign_to_object(znode *result, znode *op1, znode *op2, zval *value, temp_variable *Ts TSRMLS_DC)
{
- zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W);
+ zval **object_ptr = get_obj_zval_ptr_ptr(op1, Ts, BP_VAR_W TSRMLS_CC);
zval *object;
zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
zval tmp;
zval **retval = &Ts[result->u.var].var.ptr;
- make_real_object(object_ptr TSRMLS_CC);
+ make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
if (object->type != IS_OBJECT) {
}
/* here property is a string */
- PZVAL_UNLOCK(value);
Z_OBJ_HT_P(object)->write_property(object, property, value TSRMLS_CC);
+
+ PZVAL_UNLOCK(value);
if (property == &tmp) {
zval_dtor(property);
}
case ZEND_FETCH_STATIC_MEMBER:
return Ts[opline->op2.u.var].EA.class_entry->static_members;
break;
- case ZEND_FETCH_FROM_THIS:
- if (!EG(This)) {
- zend_error(E_ERROR, "Using $this when not in object context");
- }
- /* HACK!! 'this' should be always zend_object */
- return Z_OBJPROP_P(EG(This));
- break;
EMPTY_SWITCH_DEFAULT_CASE()
}
return NULL;
static void zend_fetch_property_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type TSRMLS_DC)
{
- zval **container_ptr = get_zval_ptr_ptr(op1, Ts, type);
+ zval **container_ptr = get_obj_zval_ptr_ptr(op1, Ts, type);
zval *container;
zval ***retval = &Ts[result->u.var].var.ptr_ptr;
SELECTIVE_PZVAL_LOCK(**retval, result);
return;
}
-
+ /* this should modify object only if it's empty */
if (container->type == IS_NULL
|| (container->type == IS_BOOL && container->value.lval==0)
|| (container->type == IS_STRING && container->value.str.len == 0)) {
retval = &Ts[result->u.var].var.ptr;
Ts[result->u.var].var.ptr_ptr = retval;
- container = get_zval_ptr(op1, Ts, &EG(free_op1), type);
+ container = get_obj_zval_ptr(op1, Ts, &EG(free_op1), type);
if (container == EG(error_zval_ptr)) {
*retval = EG(error_zval_ptr);
static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC)
{
- zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W);
+ zval **object_ptr = get_obj_zval_ptr_ptr(op1, Ts, BP_VAR_W);
zval *object;
zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
zval **retval = &Ts[result->u.var].var.ptr;
int have_get_ptr = 0;
- make_real_object(object_ptr TSRMLS_CC);
+ make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
if (object->type != IS_OBJECT) {
static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC)
{
- zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W);
+ zval **object_ptr = get_obj_zval_ptr_ptr(op1, Ts, BP_VAR_W);
zval *object;
zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
zval *retval = &Ts[result->u.var].tmp_var;
int have_get_ptr = 0;
- make_real_object(object_ptr TSRMLS_CC);
+ make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
if (object->type != IS_OBJECT) {
EX(calling_scope) = EG(scope);
- if (EX(opline)->extended_value == ZEND_FETCH_FROM_THIS) {
- if (!EG(This)) {
- zend_error(E_ERROR, "Can't fetch $this as not in object context");
- }
- EX(object) = EG(This);
- } else {
- EX(object) = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
- }
+ EX(object) = get_obj_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
if (EX(object) && EX(object)->type == IS_OBJECT) {
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(EX(object), function_name_strval, function_name_strlen TSRMLS_CC);