summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2002-10-16 18:06:36 +0000
committerStanislav Malyshev <stas@php.net>2002-10-16 18:06:36 +0000
commit349b3a096aa677b8ee3977a965b42c187b6a5bc5 (patch)
treed923e8bd2a51710e2ceb771737acaff96de92a53
parent5ce6d653b8a9e335afec9d1250241ca78e71fa25 (diff)
downloadphp-git-349b3a096aa677b8ee3977a965b42c187b6a5bc5.tar.gz
Fix and generalize $this handling.
ZEND_FETCH_FROM_THIS is removed, IS_UNUSED type on class variables will be used instead as the sign that it's a fetch from $this
-rw-r--r--Zend/zend_compile.c51
-rw-r--r--Zend/zend_compile.h2
-rw-r--r--Zend/zend_execute.c66
3 files changed, 72 insertions, 47 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index cd6815e56a..1777231fe2 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -1085,13 +1085,6 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC)
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 *));
@@ -2182,29 +2175,49 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS
(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;
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 8fac9268d5..ef045b0a61 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -204,7 +204,6 @@ typedef struct _zend_execute_data {
#define IS_VAR (1<<2)
#define IS_UNUSED (1<<3) /* Unused variable */
-
#define EXT_TYPE_UNUSED (1<<0)
#include "zend_globals.h"
@@ -617,7 +616,6 @@ int zendlex(znode *zendlval TSRMLS_DC);
#define ZEND_FETCH_LOCAL 1
#define ZEND_FETCH_STATIC 2
#define ZEND_FETCH_STATIC_MEMBER 3
-#define ZEND_FETCH_FROM_THIS 4
/* class fetches */
#define ZEND_FETCH_CLASS_DEFAULT 0
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index cf726acfad..b93c4cfefe 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -252,6 +252,7 @@ void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, z
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)) {
@@ -262,16 +263,42 @@ static inline void make_real_object(zval **object_ptr TSRMLS_DC)
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) {
@@ -301,9 +328,10 @@ static inline void zend_assign_to_object(znode *result, znode *op1, znode *op2,
}
/* 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);
}
@@ -608,13 +636,6 @@ static inline HashTable *zend_get_target_symbol_table(zend_op *opline, temp_vari
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;
@@ -885,7 +906,7 @@ static void zend_fetch_dimension_address_from_tmp_var(znode *result, znode *op1,
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;
@@ -895,7 +916,7 @@ static void zend_fetch_property_address(znode *result, znode *op1, znode *op2, t
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)) {
@@ -942,7 +963,7 @@ static void zend_fetch_property_address_read(znode *result, znode *op1, znode *o
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);
@@ -993,13 +1014,13 @@ static void zend_fetch_property_address_read(znode *result, znode *op1, znode *o
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) {
@@ -1040,13 +1061,13 @@ static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp
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) {
@@ -1908,14 +1929,7 @@ binary_assign_op_addr_obj:
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);