]> granicus.if.org Git - php/commitdiff
- Fix problem with the objects_destructor called during shutdown. It was
authorAndi Gutmans <andi@php.net>
Mon, 4 Feb 2002 19:29:56 +0000 (19:29 +0000)
committerAndi Gutmans <andi@php.net>
Mon, 4 Feb 2002 19:29:56 +0000 (19:29 +0000)
- freeing objects from id 0 instead of id 1. id 0 is not used.
- Change isset/empty opcodes to support static members and the new way of
- doing $this->foobar. Also the opcodes operate now on the hash table
- combined with the variable names so that they can be overloaded by the
- soon to be added overloading patch.

Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_objects.c

index 0132bb9ab02cd432290fb635038d954df71a7047..ba164c896928b0344afa4827713c989d9aa8bbb7 100644 (file)
@@ -2420,20 +2420,29 @@ void zend_do_unset(znode *variable, int type TSRMLS_DC)
 
 void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC)
 {
-       zend_op *opline;
+       zend_op *last_op;
 
        zend_do_end_variable_parse(BP_VAR_IS, 0 TSRMLS_CC);
-       zend_check_writable_variable(variable);
 
-       opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+       /* Check what to do with this later on when adding all of the check writable stuff
+        * zend_check_writable_variable(variable);
+        */
 
-       opline->opcode = ZEND_ISSET_ISEMPTY;
-       opline->result.op_type = IS_TMP_VAR;
-       opline->result.u.var = get_temporary_variable(CG(active_op_array));
-       opline->op1 = *variable;
-       opline->op2.u.constant.value.lval = type;
-       SET_UNUSED(opline->op2);
-       *result = opline->result;
+       last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
+       
+       switch (last_op->opcode) {
+               case ZEND_FETCH_IS:
+                       last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
+                       break;
+               case ZEND_FETCH_DIM_IS:
+               case ZEND_FETCH_OBJ_IS:
+                       last_op->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
+                       break;
+       }
+       last_op->result.op_type = IS_TMP_VAR;
+       last_op->extended_value = type;
+
+       *result = last_op->result;
 }
 
 
index 6dfa738d58863ab6c3bcb80da5defc5450f3ee59..f1eb9d0e53dd263966d0567a0988737fd787e770 100644 (file)
@@ -491,7 +491,6 @@ int zendlex(znode *zendlval TSRMLS_DC);
                                                                        
 #define ZEND_UNSET_VAR                         74
 #define ZEND_UNSET_DIM_OBJ                     75
-#define ZEND_ISSET_ISEMPTY                     76
                                                                        
 #define ZEND_FE_RESET                          77
 #define ZEND_FE_FETCH                          78
@@ -547,6 +546,9 @@ int zendlex(znode *zendlval TSRMLS_DC);
 #define ZEND_INIT_METHOD_CALL          113
 #define ZEND_INIT_STATIC_METHOD_CALL 114
 
+#define ZEND_ISSET_ISEMPTY_VAR         115
+#define ZEND_ISSET_ISEMPTY_DIM_OBJ     116
+
 /* end of block */
 
 
index 9f5dbbf8982b6abfc92714647984cd77e88307f2..5fc60237dbae2c0dcdce32c71cab5482cbb87cff 100644 (file)
@@ -521,40 +521,35 @@ static void print_refcount(zval *p, char *str)
        print_refcount(NULL, NULL);
 }
 
-
-static void zend_fetch_var_address(zend_op *opline, temp_variable *Ts, int type TSRMLS_DC)
+static inline HashTable *zend_get_target_symbol_table(zend_op *opline, temp_variable *Ts, int type TSRMLS_DC)
 {
-       int free_op1;
-       zval *varname = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R);
-       zval **retval;
-       zval tmp_varname;
-       HashTable *target_symbol_table=0;
-
        switch (opline->op2.u.EA.type) {
                case ZEND_FETCH_LOCAL:
-                       target_symbol_table = EG(active_symbol_table);
+                       return EG(active_symbol_table);
                        break;
                case ZEND_FETCH_GLOBAL:
+/* Don't think this is actually needed.
                        if (opline->op1.op_type == IS_VAR) {
                                PZVAL_LOCK(varname);
                        }
-                       target_symbol_table = &EG(symbol_table);
+*/
+                       return &EG(symbol_table);
                        break;
                case ZEND_FETCH_STATIC:
                        if (!EG(active_op_array)->static_variables) {
                                ALLOC_HASHTABLE(EG(active_op_array)->static_variables);
                                zend_hash_init(EG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
                        }
-                       target_symbol_table = EG(active_op_array)->static_variables;
+                       return EG(active_op_array)->static_variables;
                        break;
                case ZEND_FETCH_STATIC_MEMBER:
-                       target_symbol_table = Ts[opline->op2.u.var].EA.class_entry->static_members;
+                       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");
                        }
-                       target_symbol_table = Z_OBJPROP_P(EG(this));
+                       return Z_OBJPROP_P(EG(this));
                        break;
                case ZEND_FETCH_THIS:
                        {
@@ -569,11 +564,26 @@ static void zend_fetch_var_address(zend_op *opline, temp_variable *Ts, int type
                                Ts[opline->result.u.var].var.ptr_ptr = &EG(this);
                                SELECTIVE_PZVAL_LOCK(EG(this), &opline->result);
                                AI_USE_PTR(Ts[opline->result.u.var].var);
-                               return;
+                               return NULL;
                                break;
                        }
                EMPTY_SWITCH_DEFAULT_CASE()
        }
+}
+
+
+static void zend_fetch_var_address(zend_op *opline, temp_variable *Ts, int type TSRMLS_DC)
+{
+       int free_op1;
+       zval *varname = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R);
+       zval **retval;
+       zval tmp_varname;
+       HashTable *target_symbol_table;
+
+       target_symbol_table = zend_get_target_symbol_table(opline, Ts, type TSRMLS_CC);
+       if (!target_symbol_table) {
+               return;
+       }
 
        if (varname->type != IS_STRING) {
                tmp_varname = *varname;
@@ -581,6 +591,7 @@ static void zend_fetch_var_address(zend_op *opline, temp_variable *Ts, int type
                convert_to_string(&tmp_varname);
                varname = &tmp_varname;
        }
+
        if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
                switch (type) {
                        case BP_VAR_R: 
@@ -2484,7 +2495,8 @@ send_by_ref:
                                        EG(return_value_ptr_ptr) = original_return_value;
                                }
                                NEXT_OPCODE();
-                       case ZEND_UNSET_VAR: {
+                       case ZEND_UNSET_VAR:
+                               {
                                        zval tmp, *variable = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
                                        zval **object;
                                        zend_bool unset_object;
@@ -2701,54 +2713,133 @@ send_by_ref:
                                        }
                                }
                                NEXT_OPCODE();
-                       case ZEND_ISSET_ISEMPTY: {
-                                       zval **var = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_IS);
-                                       zval *value;
-                                       int isset;
-
-                                       if (!var) {
-                                               if (EX(Ts)[EX(opline)->op1.u.var].EA.type == IS_STRING_OFFSET) {
-                                                       PZVAL_LOCK(EX(Ts)[EX(opline)->op1.u.var].EA.data.str_offset.str);
-                                                       value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_IS);
-                                                       if (value->value.str.val == empty_string) {
-                                                               isset = 0;
+                       case ZEND_ISSET_ISEMPTY_VAR:
+                               {
+                                       zval tmp, *variable = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
+                                       zval **value;
+                                       zend_bool isset = 1;
+                                       HashTable *target_symbol_table;
+
+                                       target_symbol_table = zend_get_target_symbol_table(EX(opline), EX(Ts), BP_VAR_IS TSRMLS_CC);
+
+                                       if (variable->type != IS_STRING) {
+                                               tmp = *variable;
+                                               zval_copy_ctor(&tmp);
+                                               convert_to_string(&tmp);
+                                               variable = &tmp;
+                                       }
+
+                                       if (zend_hash_find(target_symbol_table, variable->value.str.val, variable->value.str.len+1, (void **) &value) == FAILURE) {
+                                               isset = 0;
+                                       }
+
+                                       EX(Ts)[EX(opline)->result.u.var].tmp_var.type = IS_BOOL;
+
+                                       switch (EX(opline)->extended_value) {
+                                               case ZEND_ISSET:
+                                                       if (isset && Z_TYPE_PP(value) == IS_NULL) {
+                                                               EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = 0;
                                                        } else {
-                                                               isset = 1;
+                                                               EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = isset;
                                                        }
-                                               } else { /* IS_OVERLOADED_OBJECT */
-                                                       value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_IS);
-                                                       if (value->type == IS_NULL) {
-                                                               isset = 0;
+                                                       break;
+                                               case ZEND_ISEMPTY:
+                                                       if (!isset || !zend_is_true(*value)) {
+                                                               EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = 1;
                                                        } else {
-                                                               isset = 1;
+                                                               EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = 0;
+                                                       }
+                                                       break;
+                                       }
+
+                                       if (variable == &tmp) {
+                                               zval_dtor(&tmp);
+                                       }
+                                       FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1));
+                               }
+                               NEXT_OPCODE();
+               case ZEND_ISSET_ISEMPTY_DIM_OBJ:
+                               {
+                                       zval **container = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_R);
+                                       zval *offset = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R);
+                                       zval **value;
+                                       int isset = 1;
+
+                                       if (container) {
+                                               HashTable *ht;
+
+                                               switch ((*container)->type) {
+                                                       case IS_ARRAY:
+                                                               ht = (*container)->value.ht;
+                                                               break;
+                                                       case IS_OBJECT:
+                                                               ht = Z_OBJPROP_PP(container);
+                                                               break;
+                                                       default:
+                                                               ht = NULL;
+                                                               break;
+                                               }
+                                               if (ht) {
+                                                       switch (offset->type) {
+                                                               case IS_DOUBLE:
+                                                               case IS_RESOURCE:
+                                                               case IS_BOOL: 
+                                                               case IS_LONG:
+                                                                       {
+                                                                               long index;
+
+                                                                               if (offset->type == IS_DOUBLE) {
+                                                                                       index = (long) offset->value.lval;
+                                                                               } else {
+                                                                                       index = offset->value.lval;
+                                                                               }
+                                                                               if (zend_hash_index_find(ht, index, (void **) &value) == FAILURE) {
+                                                                                       isset = 0;
+                                                                               }
+                                                                               break;
+                                                                       }
+                                                               case IS_STRING:
+                                                                       if (zend_hash_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == FAILURE) {
+                                                                               isset = 0;
+                                                                       }
+                                                                       break;
+                                                               case IS_NULL:
+                                                                       if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == FAILURE) {
+                                                                               isset = 0;
+                                                                       }
+                                                                       break;
+                                                               default: 
+                                                                       zend_error(E_WARNING, "Illegal offset type in unset");
+                                                                       break;
                                                        }
                                                }
-                                       } else if (*var==EG(uninitialized_zval_ptr) || ((*var)->type == IS_NULL)) {
-                                               value = *var;
-                                               isset = 0;
                                        } else {
-                                               value = *var;
-                                               isset = 1;
+                                               /* overloaded element & string offsets */
                                        }
+                                       
+                                       EX(Ts)[EX(opline)->result.u.var].tmp_var.type = IS_BOOL;
 
-                                       switch (EX(opline)->op2.u.constant.value.lval) {
+                                       switch (EX(opline)->extended_value) {
                                                case ZEND_ISSET:
-                                                       EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = isset;
+                                                       if (isset && Z_TYPE_PP(value) == IS_NULL) {
+                                                               EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = 0;
+                                                       } else {
+                                                               EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = isset;
+                                                       }
                                                        break;
                                                case ZEND_ISEMPTY:
-                                                       if (!isset || !zend_is_true(value)) {
+                                                       if (!isset || !zend_is_true(*value)) {
                                                                EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = 1;
                                                        } else {
                                                                EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = 0;
                                                        }
                                                        break;
                                        }
-                                       EX(Ts)[EX(opline)->result.u.var].tmp_var.type = IS_BOOL;
-                                       if (!var) {
-                                               FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1));
-                                       }
+
+                                       FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2));
                                }
                                NEXT_OPCODE();
+                               break;
                        case ZEND_EXIT:
                                if (EX(opline)->op1.op_type != IS_UNUSED) {
                                        zval *ptr;
index bdb77f05d0175f32fac65a5753a96accd8dc1b97..ddbbee5f2ae28c02acb3ac1e591b94a8da7dc7b7 100644 (file)
@@ -72,9 +72,9 @@ static inline void zend_objects_destroy_object(zend_object *object, zend_object_
 
 void zend_objects_call_destructors(zend_objects *objects TSRMLS_DC)
 {
-       int i = 1;
+       zend_uint i = 1;
 
-       for (i = 0; i < objects->top ; i++) {
+       for (i = 1; i < objects->top ; i++) {
                if (EG(objects).object_buckets[i].valid) {
                        EG(objects).object_buckets[i].constructor_called = 1;
                        zend_objects_destroy_object(&EG(objects).object_buckets[i].bucket.obj.object, i TSRMLS_CC);