Changeset 124

Show
Ignore:
Timestamp:
07/11/05 19:25:38 (3 years ago)
Author:
zoeloelip
Message:

* ea_store.c and ea_restore.c functions clean up
* extraced restore_class_parent and restore_class_methods from

restore_class_entry to share code with loader.c

* extracted opcode handling in encode/decode_op_array into

encode/decode_op to make code more readable

* make decode_class_entry use new functions in ea_restore.c
* readded line-number encoding
* bumped up encoder version to 4 until new loader is in place

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • eaccelerator/trunk/ChangeLog

    r123 r124  
     12005-07-11 Bart Vanbrabant <bart.vanbrabant at zoeloelip.be> 
     2        * ea_store.c and ea_restore.c functions clean up 
     3        * extraced restore_class_parent and restore_class_methods from 
     4          restore_class_entry to share code with loader.c 
     5        * extracted opcode handling in encode/decode_op_array into  
     6          encode/decode_op to make code more readable 
     7        * make decode_class_entry use new functions in ea_restore.c 
     8        * readded line-number encoding 
     9        * bumped up encoder version to 4 until new loader is in place 
     10 
    1112005-07-10 Bart Vanbrabant <bart.vanbrabant at zoeloelip.be> 
    212 
  • eaccelerator/trunk/ea_restore.c

    r123 r124  
    5656/* This function creates a dummy class entry to steal the pointer to the 
    5757 * properties_info hashtable destructor because it's declared static */ 
    58 dtor_func_t get_zend_destroy_property_info(TSRMLS_D) { 
    59     dtor_func_t property_dtor; 
    60     zend_class_entry dummy_class_entry; 
    61     dummy_class_entry.type = ZEND_USER_CLASS; 
    62  
    63     zend_initialize_class_data(&dummy_class_entry, 1 TSRMLS_CC); 
    64  
    65     property_dtor = dummy_class_entry.properties_info.pDestructor; 
    66  
    67     zend_hash_destroy(&dummy_class_entry.default_properties); 
    68     zend_hash_destroy(&dummy_class_entry.properties_info); 
    69     zend_hash_destroy(dummy_class_entry.static_members); 
    70     zend_hash_destroy(&dummy_class_entry.function_table); 
    71     FREE_HASHTABLE(dummy_class_entry.static_members); 
    72     zend_hash_destroy(&dummy_class_entry.constants_table); 
    73  
    74     return property_dtor; 
     58dtor_func_t get_zend_destroy_property_info(TSRMLS_D) 
     59
     60        dtor_func_t property_dtor; 
     61        zend_class_entry dummy_class_entry; 
     62        dummy_class_entry.type = ZEND_USER_CLASS; 
     63 
     64        zend_initialize_class_data(&dummy_class_entry, 1 TSRMLS_CC); 
     65 
     66        property_dtor = dummy_class_entry.properties_info.pDestructor; 
     67 
     68        zend_hash_destroy(&dummy_class_entry.default_properties); 
     69        zend_hash_destroy(&dummy_class_entry.properties_info); 
     70        zend_hash_destroy(dummy_class_entry.static_members); 
     71        zend_hash_destroy(&dummy_class_entry.function_table); 
     72        FREE_HASHTABLE(dummy_class_entry.static_members); 
     73        zend_hash_destroy(&dummy_class_entry.constants_table); 
     74 
     75        return property_dtor; 
    7576} 
    7677#endif 
     
    8687 
    8788#ifdef ZEND_ENGINE_2 
    88 static void fixup_property_info (zend_property_info * from TSRMLS_DC) 
    89 
    90     FIXUP (from->name); 
    91 
    92 #endif 
    93  
    94 static void fixup_hash (HashTable * source, 
    95         fixup_bucket_t fixup_bucket TSRMLS_DC) 
    96 
    97     unsigned int i; 
    98     Bucket *p; 
    99  
    100     if (source->nNumOfElements > 0) { 
    101         if (!EAG (compress)) { 
    102             if (source->arBuckets != NULL) { 
    103                 FIXUP (source->arBuckets); 
    104                 for (i = 0; i < source->nTableSize; i++) { 
    105                     FIXUP (source->arBuckets[i]); 
     89static void fixup_property_info(zend_property_info * from TSRMLS_DC) 
     90
     91        FIXUP(from->name); 
     92
     93#endif 
     94 
     95static void fixup_hash(HashTable * source, 
     96                                           fixup_bucket_t fixup_bucket TSRMLS_DC) 
     97
     98        unsigned int i; 
     99        Bucket *p; 
     100 
     101        if (source->nNumOfElements > 0) { 
     102                if (!EAG(compress)) { 
     103                        if (source->arBuckets != NULL) { 
     104                                FIXUP(source->arBuckets); 
     105                                for (i = 0; i < source->nTableSize; i++) { 
     106                                        FIXUP(source->arBuckets[i]); 
     107                                } 
     108                        } 
     109                } 
     110                FIXUP(source->pListHead); 
     111                FIXUP(source->pListTail); 
     112 
     113                p = source->pListHead; 
     114                while (p) { 
     115                        FIXUP(p->pNext); 
     116                        FIXUP(p->pLast); 
     117                        FIXUP(p->pData); 
     118                        FIXUP(p->pDataPtr); 
     119                        FIXUP(p->pListLast); 
     120                        FIXUP(p->pListNext); 
     121                        if (p->pDataPtr) { 
     122                                fixup_bucket(p->pDataPtr TSRMLS_CC); 
     123                                p->pData = &p->pDataPtr; 
     124                        } else { 
     125                                fixup_bucket(p->pData TSRMLS_CC); 
     126                        } 
     127                        p = p->pListNext; 
     128                } 
     129                source->pInternalPointer = source->pListHead; 
     130        } 
     131
     132 
     133void fixup_zval(zval * zv TSRMLS_DC) 
     134
     135        switch (zv->type & ~IS_CONSTANT_INDEX) { 
     136        case IS_CONSTANT:                       /* fallthrough */ 
     137        case IS_STRING: 
     138                if (zv->value.str.val == NULL || zv->value.str.len == 0) { 
     139                        zv->value.str.val = empty_string; 
     140                        zv->value.str.len = 0; 
     141                } else { 
     142                        FIXUP(zv->value.str.val); 
     143                } 
     144                break; 
     145        case IS_ARRAY:                          /* fallthrough */ 
     146        case IS_CONSTANT_ARRAY: 
     147                if (zv->value.ht == NULL || zv->value.ht == &EG(symbol_table)) { 
     148                } else { 
     149                        FIXUP(zv->value.ht); 
     150                        fixup_zval_hash(zv->value.ht); 
     151                } 
     152                break; 
     153        case IS_OBJECT: 
     154                if (!EAG(compress)) { 
     155                        return; 
     156                } 
     157#ifndef ZEND_ENGINE_2 
     158                FIXUP(zv->value.obj.ce); 
     159                if (zv->value.obj.properties != NULL) { 
     160                        FIXUP(zv->value.obj.properties); 
     161                        fixup_zval_hash(zv->value.obj.properties); 
     162                } 
     163#endif 
     164        default: 
     165                break; 
     166        } 
     167
     168 
     169void fixup_op_array(eaccelerator_op_array * from TSRMLS_DC) 
     170
     171        zend_op *opline; 
     172        zend_op *end; 
     173 
     174#ifdef ZEND_ENGINE_2 
     175        if (from->num_args > 0) { 
     176                zend_uint i; 
     177                FIXUP(from->arg_info); 
     178                for (i = 0; i < from->num_args; i++) { 
     179                        FIXUP(from->arg_info[i].name); 
     180                        FIXUP(from->arg_info[i].class_name); 
     181                } 
     182        } 
     183#else 
     184        FIXUP(from->arg_types); 
     185#endif 
     186        FIXUP(from->function_name); 
     187#ifdef ZEND_ENGINE_2 
     188        FIXUP(from->scope_name); 
     189#endif 
     190        if (from->type == ZEND_INTERNAL_FUNCTION) { 
     191                return; 
     192        } 
     193 
     194        if (from->opcodes != NULL) { 
     195                FIXUP(from->opcodes); 
     196 
     197                opline = from->opcodes; 
     198                end = opline + from->last; 
     199                EAG(compress) = 0; 
     200                for (; opline < end; opline++) { 
     201                        /* 
     202                           if (opline->result.op_type == IS_CONST)  
     203                           fixup_zval(&opline->result.u.constant TSRMLS_CC); 
     204                         */ 
     205                        if (opline->op1.op_type == IS_CONST) 
     206                                fixup_zval(&opline->op1.u.constant TSRMLS_CC); 
     207                        if (opline->op2.op_type == IS_CONST) 
     208                                fixup_zval(&opline->op2.u.constant TSRMLS_CC); 
     209#ifdef ZEND_ENGINE_2 
     210                        switch (opline->opcode) { 
     211                        case ZEND_JMP: 
     212                                FIXUP(opline->op1.u.jmp_addr); 
     213                                break; 
     214                        case ZEND_JMPZ: /* fallthrough */ 
     215                        case ZEND_JMPNZ: 
     216                        case ZEND_JMPZ_EX: 
     217                        case ZEND_JMPNZ_EX: 
     218                                FIXUP(opline->op2.u.jmp_addr); 
     219                                break; 
     220                        } 
     221                        opline->handler = get_opcode_handler(opline->opcode TSRMLS_CC); 
     222#endif 
     223                } 
     224                EAG(compress) = 1; 
     225        } 
     226        FIXUP(from->brk_cont_array); 
     227#ifdef ZEND_ENGINE_2 
     228        FIXUP(from->try_catch_array); 
     229#endif 
     230        if (from->static_variables != NULL) { 
     231                FIXUP(from->static_variables); 
     232                fixup_zval_hash(from->static_variables); 
     233        } 
     234        FIXUP(from->filename); 
     235#ifdef ZEND_ENGINE_2 
     236        FIXUP(from->doc_comment); 
     237#endif 
     238
     239 
     240void fixup_class_entry(eaccelerator_class_entry * from TSRMLS_DC) 
     241
     242        FIXUP(from->name); 
     243        FIXUP(from->parent); 
     244#ifdef ZEND_ENGINE_2 
     245        FIXUP(from->filename); 
     246        FIXUP(from->doc_comment); 
     247        fixup_zval_hash(&from->constants_table); 
     248        fixup_zval_hash(&from->default_properties); 
     249        fixup_hash(&from->properties_info, 
     250                           (fixup_bucket_t) fixup_property_info TSRMLS_CC); 
     251        if (from->static_members != NULL) { 
     252                FIXUP(from->static_members); 
     253                fixup_zval_hash(from->static_members); 
     254        } 
     255#else 
     256        fixup_zval_hash(&from->default_properties); 
     257#endif 
     258        fixup_hash(&from->function_table, 
     259                           (fixup_bucket_t) fixup_op_array TSRMLS_CC); 
     260
     261 
     262/******************************************************************************/ 
     263/* Functions to restore a php script from shared memory                       */ 
     264/******************************************************************************/ 
     265 
     266typedef void *(*restore_bucket_t) (void *TSRMLS_DC); 
     267 
     268#define restore_zval_hash(target, source) \ 
     269    restore_hash(target, source, (restore_bucket_t)restore_zval_ptr TSRMLS_CC) 
     270 
     271static zval *restore_zval_ptr(zval * from TSRMLS_DC) 
     272
     273        zval *p; 
     274        ALLOC_ZVAL(p); 
     275        memcpy(p, from, sizeof(zval)); 
     276        restore_zval(p TSRMLS_CC); 
     277        return p; 
     278
     279 
     280static HashTable *restore_hash(HashTable * target, HashTable * source, 
     281                                                           restore_bucket_t copy_bucket TSRMLS_DC) 
     282
     283        Bucket *p, *np, *prev_p; 
     284        int nIndex; 
     285 
     286        if (target == NULL) { 
     287                ALLOC_HASHTABLE(target); 
     288        } 
     289        memcpy(target, source, sizeof(HashTable)); 
     290        target->arBuckets = 
     291                (Bucket **) emalloc(target->nTableSize * sizeof(Bucket *)); 
     292        memset(target->arBuckets, 0, target->nTableSize * sizeof(Bucket *)); 
     293        target->pDestructor = NULL; 
     294        target->persistent = 0; 
     295        target->pListHead = NULL; 
     296        target->pListTail = NULL; 
     297 
     298        p = source->pListHead; 
     299        prev_p = NULL; 
     300        np = NULL; 
     301        while (p) { 
     302                np = (Bucket *) emalloc(offsetof(Bucket, arKey) + p->nKeyLength); 
     303                /*    np = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength); */ 
     304                nIndex = p->h % source->nTableSize; 
     305                if (target->arBuckets[nIndex]) { 
     306                        np->pNext = target->arBuckets[nIndex]; 
     307                        np->pLast = NULL; 
     308                        np->pNext->pLast = np; 
     309                } else { 
     310                        np->pNext = NULL; 
     311                        np->pLast = NULL; 
     312                } 
     313                target->arBuckets[nIndex] = np; 
     314                np->h = p->h; 
     315                np->nKeyLength = p->nKeyLength; 
     316 
     317                if (p->pDataPtr == NULL) { 
     318                        np->pData = copy_bucket(p->pData TSRMLS_CC); 
     319                        np->pDataPtr = NULL; 
     320                } else { 
     321                        np->pDataPtr = copy_bucket(p->pDataPtr TSRMLS_CC); 
     322                        np->pData = &np->pDataPtr; 
     323                } 
     324                np->pListLast = prev_p; 
     325                np->pListNext = NULL; 
     326 
     327                memcpy(np->arKey, p->arKey, p->nKeyLength); 
     328 
     329                if (prev_p) { 
     330                        prev_p->pListNext = np; 
     331                } else { 
     332                        target->pListHead = np; 
     333                } 
     334                prev_p = np; 
     335                p = p->pListNext; 
     336        } 
     337        target->pListTail = np; 
     338        target->pInternalPointer = target->pListHead; 
     339        return target; 
     340
     341 
     342void restore_zval(zval * zv TSRMLS_DC) 
     343
     344        switch (zv->type & ~IS_CONSTANT_INDEX) { 
     345        case IS_CONSTANT: 
     346        case IS_STRING: 
     347                if (zv->value.str.val == NULL ||  
     348                zv->value.str.val == empty_string || zv->value.str.len == 0) { 
     349                        zv->value.str.val = empty_string; 
     350                        return; 
     351                } else { 
     352                        char *p = emalloc(zv->value.str.len + 1); 
     353                        memcpy(p, zv->value.str.val, zv->value.str.len + 1); 
     354                        zv->value.str.val = p; 
     355                } 
     356                return; 
     357 
     358        case IS_ARRAY: 
     359        case IS_CONSTANT_ARRAY: 
     360                if (zv->value.ht != NULL && zv->value.ht != &EG(symbol_table)) { 
     361                        zv->value.ht = restore_zval_hash(NULL, zv->value.ht); 
     362                        zv->value.ht->pDestructor = ZVAL_PTR_DTOR; 
     363                } 
     364                return; 
     365 
     366        case IS_OBJECT: 
     367    { 
     368#ifndef ZEND_ENGINE_2 
     369        zend_bool incomplete_class = 0; 
     370        char *class_name = (char *) zv->value.obj.ce; 
     371        int name_len = 0; 
     372        if (!EAG(compress)) { 
     373            return; 
     374        } 
     375        if (class_name != NULL) { 
     376            zend_class_entry *ce = NULL; 
     377            name_len = strlen(class_name); 
     378            if (zend_hash_find(CG(class_table), (void *) class_name, name_len + 1, (void **) &ce) != SUCCESS) { 
     379                char *lowercase_name = estrndup(INCOMPLETE_CLASS, sizeof(INCOMPLETE_CLASS)); 
     380                zend_str_tolower(lowercase_name, sizeof(INCOMPLETE_CLASS)); 
     381                if (zend_hash_find(CG(class_table), lowercase_name, 
     382                            sizeof(INCOMPLETE_CLASS), (void **) &ce) != SUCCESS) { 
     383                    efree(lowercase_name); 
     384                    zend_error(E_ERROR, "EACCELERATOR can't restore object's class \"%s\"", class_name); 
     385                } else { 
     386                    efree(lowercase_name); 
     387                    zv->value.obj.ce = ce; 
     388                    incomplete_class = 1; 
     389                } 
     390            } else { 
     391                zv->value.obj.ce = ce; 
     392            } 
     393        } 
     394        if (zv->value.obj.properties != NULL) { 
     395            zv->value.obj.properties = restore_zval_hash(NULL, zv->value.obj.properties); 
     396            zv->value.obj.properties->pDestructor = ZVAL_PTR_DTOR; 
     397            /* Clearing references */ 
     398            { 
     399                Bucket *p = zv->value.obj.properties->pListHead; 
     400                while (p != NULL) { 
     401                    ((zval *) (p->pDataPtr))->refcount = 1; 
     402                    p = p->pListNext; 
    106403                } 
    107404            } 
    108405        } 
    109         FIXUP (source->pListHead); 
    110         FIXUP (source->pListTail); 
    111  
    112         p = source->pListHead; 
    113         while (p) { 
    114             FIXUP (p->pNext); 
    115             FIXUP (p->pLast); 
    116             FIXUP (p->pData); 
    117             FIXUP (p->pDataPtr); 
    118             FIXUP (p->pListLast); 
    119             FIXUP (p->pListNext); 
    120             if (p->pDataPtr) { 
    121                 fixup_bucket (p->pDataPtr TSRMLS_CC); 
    122                 p->pData = &p->pDataPtr; 
    123             } else { 
    124                 fixup_bucket (p->pData TSRMLS_CC); 
    125             } 
    126             p = p->pListNext; 
     406        if (incomplete_class && class_name != NULL) { 
     407            zval *val; 
     408            MAKE_STD_ZVAL(val); 
     409            Z_TYPE_P(val) = IS_STRING; 
     410            Z_STRVAL_P(val) = estrndup(class_name, name_len); 
     411            Z_STRLEN_P(val) = name_len; 
     412            zend_hash_update(Z_OBJPROP_P(zv), MAGIC_MEMBER, sizeof(MAGIC_MEMBER), &val, sizeof(val), NULL); 
    127413        } 
    128         source->pInternalPointer = source->pListHead; 
    129     } 
    130 
    131  
    132 void fixup_zval (zval * zv TSRMLS_DC) 
    133 
    134     switch (zv->type & ~IS_CONSTANT_INDEX) { 
    135         case IS_CONSTANT: /* fallthrough */ 
    136         case IS_STRING: 
    137             if (zv->value.str.val == NULL || zv->value.str.len == 0) { 
    138                 zv->value.str.val = empty_string; 
    139                 zv->value.str.len = 0; 
    140             } else { 
    141                 FIXUP (zv->value.str.val); 
    142             } 
    143             break; 
    144         case IS_ARRAY: /* fallthrough */ 
    145         case IS_CONSTANT_ARRAY: 
    146             if (zv->value.ht == NULL || zv->value.ht == &EG (symbol_table)) { 
    147             } else { 
    148                 FIXUP (zv->value.ht); 
    149                 fixup_zval_hash (zv->value.ht); 
    150             } 
    151             break; 
    152         case IS_OBJECT: 
    153             if (!EAG (compress)) { 
    154                 return; 
    155             } 
    156 #ifndef ZEND_ENGINE_2 
    157             FIXUP (zv->value.obj.ce); 
    158             if (zv->value.obj.properties != NULL) { 
    159                 FIXUP (zv->value.obj.properties); 
    160                 fixup_zval_hash (zv->value.obj.properties); 
    161             } 
    162 #endif 
    163         default: 
    164             break; 
    165     } 
    166 
    167  
    168 void fixup_op_array (eaccelerator_op_array * from TSRMLS_DC) 
    169 
    170     zend_op *opline; 
    171     zend_op *end; 
    172  
    173 #ifdef ZEND_ENGINE_2 
    174     if (from->num_args > 0) { 
    175         zend_uint i; 
    176         FIXUP (from->arg_info); 
    177         for (i = 0; i < from->num_args; i++) { 
    178             FIXUP (from->arg_info[i].name); 
    179             FIXUP (from->arg_info[i].class_name); 
    180         } 
    181     } 
    182 #else 
    183     FIXUP (from->arg_types); 
    184 #endif 
    185     FIXUP (from->function_name); 
    186 #ifdef ZEND_ENGINE_2 
    187     FIXUP (from->scope_name); 
    188 #endif 
    189     if (from->type == ZEND_INTERNAL_FUNCTION) { 
     414#endif 
    190415        return; 
    191416    } 
    192  
    193     if (from->opcodes != NULL) { 
    194         FIXUP (from->opcodes); 
    195  
    196         opline = from->opcodes; 
    197         end = opline + from->last; 
    198         EAG (compress) = 0; 
    199         for (; opline < end; opline++) { 
    200             /* 
    201                if (opline->result.op_type == IS_CONST) fixup_zval(&opline->result.u.constant  TSRMLS_CC); 
    202              */ 
    203             if (opline->op1.op_type == IS_CONST) 
    204                 fixup_zval (&opline->op1.u.constant TSRMLS_CC); 
    205             if (opline->op2.op_type == IS_CONST) 
    206                 fixup_zval (&opline->op2.u.constant TSRMLS_CC); 
    207 #ifdef ZEND_ENGINE_2 
    208             switch (opline->opcode) { 
    209                 case ZEND_JMP: 
    210                     FIXUP (opline->op1.u.jmp_addr); 
    211                     break; 
    212                 case ZEND_JMPZ: /* fallthrough */ 
    213                 case ZEND_JMPNZ: 
    214                 case ZEND_JMPZ_EX: 
    215                 case ZEND_JMPNZ_EX: 
    216                     FIXUP (opline->op2.u.jmp_addr); 
    217                     break; 
    218             } 
    219             opline->handler = get_opcode_handler (opline->opcode TSRMLS_CC); 
    220 #endif 
    221         } 
    222         EAG (compress) = 1; 
    223     } 
    224     FIXUP (from->brk_cont_array); 
    225 #ifdef ZEND_ENGINE_2 
    226     FIXUP (from->try_catch_array); 
    227 #endif 
    228     if (from->static_variables != NULL) { 
    229         FIXUP (from->static_variables); 
    230         fixup_zval_hash (from->static_variables); 
    231     } 
    232     FIXUP (from->filename); 
    233 #ifdef ZEND_ENGINE_2 
    234     FIXUP (from->doc_comment); 
    235 #endif 
    236 
    237  
    238 void fixup_class_entry (eaccelerator_class_entry * from TSRMLS_DC) 
    239 
    240     FIXUP (from->name); 
    241     FIXUP (from->parent); 
    242 #ifdef ZEND_ENGINE_2 
    243     FIXUP (from->filename); 
    244     FIXUP (from->doc_comment); 
    245     fixup_zval_hash (&from->constants_table); 
    246     fixup_zval_hash (&from->default_properties); 
    247     fixup_hash (&from->properties_info, 
    248             (fixup_bucket_t) fixup_property_info TSRMLS_CC); 
    249     if (from->static_members != NULL) { 
    250         FIXUP (from->static_members); 
    251         fixup_zval_hash (from->static_members); 
    252     } 
    253 #else 
    254     fixup_zval_hash (&from->default_properties); 
    255 #endif 
    256     fixup_hash (&from->function_table, 
    257             (fixup_bucket_t) fixup_op_array TSRMLS_CC); 
    258 
    259  
    260 /******************************************************************************/ 
    261 /* Functions to restore a php script from shared memory                       */ 
    262 /******************************************************************************/ 
    263  
    264 typedef void *(*restore_bucket_t) (void *TSRMLS_DC); 
    265  
    266 #define restore_zval_hash(target, source) \ 
    267     restore_hash(target, source, (restore_bucket_t)restore_zval_ptr TSRMLS_CC) 
    268  
    269 static zval *restore_zval_ptr (zval * from TSRMLS_DC) 
    270 
    271     zval *p; 
    272     ALLOC_ZVAL (p); 
    273     memcpy (p, from, sizeof (zval)); 
    274     restore_zval (p TSRMLS_CC); 
    275     return p; 
    276 
    277  
    278 static HashTable *restore_hash (HashTable * target, HashTable * source, 
    279         restore_bucket_t copy_bucket TSRMLS_DC) 
    280 
    281     Bucket *p, *np, *prev_p; 
    282     int nIndex; 
    283  
    284     if (target == NULL) { 
    285         ALLOC_HASHTABLE (target); 
    286     } 
    287     memcpy (target, source, sizeof (HashTable)); 
    288     target->arBuckets = 
    289         (Bucket **) emalloc (target->nTableSize * sizeof (Bucket *)); 
    290     memset (target->arBuckets, 0, target->nTableSize * sizeof (Bucket *)); 
    291     target->pDestructor = NULL; 
    292     target->persistent = 0; 
    293     target->pListHead = NULL; 
    294     target->pListTail = NULL; 
    295  
    296     p = source->pListHead; 
    297     prev_p = NULL; 
    298     np = NULL; 
    299     while (p) { 
    300         np = (Bucket *) emalloc (offsetof (Bucket, arKey) + p->nKeyLength); 
    301         /*    np = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength);*/ 
    302         nIndex = p->h % source->nTableSize; 
    303         if (target->arBuckets[nIndex]) { 
    304             np->pNext = target->arBuckets[nIndex]; 
    305             np->pLast = NULL; 
    306             np->pNext->pLast = np; 
    307         } else { 
    308             np->pNext = NULL; 
    309             np->pLast = NULL; 
    310         } 
    311         target->arBuckets[nIndex] = np; 
    312         np->h = p->h; 
    313         np->nKeyLength = p->nKeyLength; 
    314  
    315         if (p->pDataPtr == NULL) { 
    316             np->pData = copy_bucket (p->pData TSRMLS_CC); 
    317             np->pDataPtr = NULL; 
    318         } else { 
    319             np->pDataPtr = copy_bucket (p->pDataPtr TSRMLS_CC); 
    320             np->pData = &np->pDataPtr; 
    321         } 
    322         np->pListLast = prev_p; 
    323         np->pListNext = NULL; 
    324  
    325         memcpy (np->arKey, p->arKey, p->nKeyLength); 
    326  
    327         if (prev_p) { 
    328             prev_p->pListNext = np; 
    329         } else { 
    330             target->pListHead = np; 
    331         } 
    332         prev_p = np; 
    333         p = p->pListNext; 
    334     } 
    335     target->pListTail = np; 
    336     target->pInternalPointer = target->pListHead; 
    337     return target; 
    338 
    339  
    340 void restore_zval (zval * zv TSRMLS_DC) 
    341 
    342     switch (zv->type & ~IS_CONSTANT_INDEX) { 
    343         case IS_CONSTANT: 
    344         case IS_STRING: 
    345             if (zv->value.str.val == NULL || zv->value.str.val == empty_string 
    346                     || zv->value.str.len == 0) { 
    347                 zv->value.str.val = empty_string; 
    348                 return; 
    349             } else { 
    350                 char *p = emalloc (zv->value.str.len + 1); 
    351                 memcpy (p, zv->value.str.val, zv->value.str.len + 1); 
    352                 zv->value.str.val = p; 
    353             } 
    354             return; 
    355  
    356         case IS_ARRAY: 
    357         case IS_CONSTANT_ARRAY: 
    358             if (zv->value.ht != NULL && zv->value.ht != &EG (symbol_table)) { 
    359                 zv->value.ht = restore_zval_hash (NULL, zv->value.ht); 
    360                 zv->value.ht->pDestructor = ZVAL_PTR_DTOR; 
    361             } 
    362             return; 
    363          
    364         case IS_OBJECT: 
    365             { 
     417        } 
     418
     419 
     420static void call_op_array_ctor_handler(zend_extension * extension, 
     421                                                                           zend_op_array * op_array TSRMLS_DC) 
     422
     423        if (extension->op_array_ctor) { 
     424                extension->op_array_ctor(op_array); 
     425        } 
     426
     427 
     428zend_op_array *restore_op_array(zend_op_array * to, 
     429                                                                eaccelerator_op_array * from TSRMLS_DC) 
     430
     431        zend_function *function; 
     432#ifdef ZEND_ENGINE_2 
     433        int fname_len = 0; 
     434        char *fname_lc = NULL; 
     435#endif 
     436 
     437        ea_debug_pad(EA_DEBUG TSRMLS_CC); 
     438        ea_debug_printf(EA_DEBUG, "[%d] restore_op_array: %s\n", getpid(), 
     439                                        from->function_name ? from->function_name : "(top)"); 
     440 
     441        if (from->type == ZEND_INTERNAL_FUNCTION) { 
     442                if (to == NULL) { 
     443                        to = emalloc(sizeof(zend_internal_function)); 
     444                } 
     445                memset(to, 0, sizeof(zend_internal_function)); 
     446        } else { 
     447                if (to == NULL) { 
     448                        to = emalloc(sizeof(zend_op_array)); 
     449                } 
     450                memset(to, 0, sizeof(zend_op_array)); 
     451                if (ZendOptimizer) { 
     452                        zend_llist_apply_with_argument(&zend_extensions,  
     453                    (llist_apply_with_arg_func_t) call_op_array_ctor_handler, to TSRMLS_CC); 
     454                } 
     455        } 
     456        to->type = from->type; 
     457#ifdef ZEND_ENGINE_2 
     458        to->num_args = from->num_args; 
     459        to->required_num_args = from->required_num_args; 
     460        to->arg_info = from->arg_info; 
     461        to->pass_rest_by_reference = from->pass_rest_by_reference; 
     462#else 
     463        to->arg_types = from->arg_types; 
     464#endif 
     465        to->function_name = from->function_name; 
     466 
     467#ifdef ZEND_ENGINE_2 
     468        if (to->function_name) { 
     469                fname_len = strlen(to->function_name); 
     470                fname_lc = zend_str_tolower_dup(to->function_name, fname_len); 
     471        } 
     472 
     473        to->fn_flags = from->fn_flags; 
     474 
     475        /* segv74: 
     476         * to->scope = EAG(class_entry) 
     477         * 
     478         * if  from->scope_name == NULL, 
     479         *     ; EAG(class) == NULL  : we are in function or outside function. 
     480         *     ; EAG(class) != NULL  : inherited method not defined in current file, should have to find. 
     481         *                              just LINK (zend_op_array *) to to original entry in parent, 
     482         *                              but, with what? !!! I don't know PARENT CLASS NAME !!!! 
     483         * 
     484         * 
     485         * if  from->scope_name != NULL, 
     486         *     ; we are in class member function  
     487         * 
     488         *     ; we have to find appropriate (zend_class_entry*) to->scope for name from->scope_name 
     489         *     ; if we find in CG(class_table), link to it. 
     490         *     ; if fail, it should be EAG(class_entry) 
     491         *     
     492         * am I right here ? ;-( 
     493         */ 
     494        if (from->scope_name != NULL) { 
     495                char *from_scope_lc = zend_str_tolower_dup(from->scope_name, from->scope_name_len); 
     496                if (zend_hash_find (CG(class_table), (void *) from_scope_lc,  
     497                    from->scope_name_len + 1, (void **) &to->scope) != SUCCESS) { 
     498                        ea_debug_pad(EA_DEBUG TSRMLS_CC); 
     499                        ea_debug_printf(EA_DEBUG, "[%d]                   can't find '%s' in hash. use EAG(class_entry).\n", getpid(), from_scope_lc); 
     500                        to->scope = EAG(class_entry); 
     501                } else { 
     502                        ea_debug_pad(EA_DEBUG TSRMLS_CC); 
     503                        ea_debug_printf(EA_DEBUG, "[%d]                   found '%s' in hash\n", getpid(), from_scope_lc); 
     504                        to->scope = *(zend_class_entry **) to->scope; 
     505                } 
     506                efree(from_scope_lc); 
     507        } else {                                        // zoeloelip: is this needed? scope is always stored 
     508                ea_debug_pad(EA_DEBUG TSRMLS_CC); 
     509                ea_debug_printf(EA_DEBUG, "[%d]                   from is NULL\n", getpid());  
     510                if (EAG(class_entry)) { 
     511                        zend_class_entry *p; 
     512                        for (p = EAG(class_entry)->parent; p; p = p->parent) { 
     513                                ea_debug_pad(EA_DEBUG TSRMLS_CC); 
     514                                ea_debug_printf(EA_DEBUG, "[%d]                   checking parent '%s' have '%s'\n", getpid(), p->name, fname_lc); 
     515                                if (zend_hash_find(&p->function_table, fname_lc, fname_len + 1, (void **) &function) == SUCCESS) { 
     516                                        ea_debug_pad(EA_DEBUG TSRMLS_CC); 
     517                                        ea_debug_printf(EA_DEBUG, "[%d]                                   '%s' has '%s' of scope '%s'\n",  
     518                            getpid(), p->name, fname_lc, function->common.scope->name); 
     519                                        to->scope = function->common.scope; 
     520                                        break; 
     521                                } 
     522                        } 
     523                } else { 
     524                        to->scope = NULL; 
     525                } 
     526        } 
     527 
     528        ea_debug_pad(EA_DEBUG TSRMLS_CC); 
     529        ea_debug_printf(EA_DEBUG, "[%d]                   %s's scope is '%s'\n", getpid(),  
     530            from->function_name ? from->function_name : "(top)", to->scope ? to->scope->name : "NULL"); 
     531#endif 
     532        if (from->type == ZEND_INTERNAL_FUNCTION) { 
     533                zend_class_entry *class_entry = EAG(class_entry); 
     534                ea_debug_pad(EA_DEBUG TSRMLS_CC); 
     535                ea_debug_printf(EA_DEBUG, "[%d]                   [internal function from=%08x,to=%08x] class_entry='%s' [%08x]\n",  
     536                getpid(), from, to, class_entry->name, class_entry); 
     537                if (class_entry) { 
     538                        ea_debug_pad(EA_DEBUG TSRMLS_CC); 
     539                        ea_debug_printf(EA_DEBUG, "[%d]                                       class_entry->parent='%s' [%08x]\n",  
     540                    getpid(), class_entry->parent->name, class_entry->parent); 
     541                } 
     542                if (class_entry != NULL && class_entry->parent != NULL &&  
     543                zend_hash_find(&class_entry->parent->function_table, 
     544#ifdef ZEND_ENGINE_2 
     545                fname_lc, fname_len + 1, 
     546#else 
     547                to->function_name, strlen(to->function_name) + 1, 
     548#endif 
     549                                (void **) &function) == SUCCESS && function->type == ZEND_INTERNAL_FUNCTION) { 
     550                        ea_debug_pad(EA_DEBUG TSRMLS_CC); 
     551                        ea_debug_printf(EA_DEBUG, "[%d]                                       found in function table\n", getpid()); 
     552                        ((zend_internal_function *) (to))->handler = ((zend_internal_function *) function)->handler; 
     553                } else { 
     554                        /* FIXME. I don't know how to fix handler. 
     555                         * TODO: must solve this somehow, to avoid returning damaged structure... 
     556                         */ 
     557                        ea_debug_pad(EA_DEBUG TSRMLS_CC); 
     558                        ea_debug_printf(EA_DEBUG, "[%d]                                       can't find\n", getpid()); 
     559                } 
     560                return to; 
     561        } 
     562        to->opcodes = from->opcodes; 
     563        to->last = to->size = from->last; 
     564        to->T = from->T; 
     565        to->brk_cont_array = from->brk_cont_array; 
     566        to->last_brk_cont = from->last_brk_cont; 
     567        /* 
     568           to->current_brk_cont = -1; 
     569           to->static_variables = from->static_variables; 
     570           to->start_op         = to->opcodes; 
     571           to->backpatch_count  = 0; 
     572         */ 
     573        to->return_reference = from->return_reference; 
     574        to->done_pass_two = 1; 
     575        to->filename = from->filename; 
     576#ifdef ZEND_ENGINE_2 
     577        /* HOESH: try & catch support */ 
     578        to->try_catch_array = from->try_catch_array; 
     579        to->last_try_catch = from->last_try_catch; 
     580        to->uses_this = from->uses_this; 
     581 
     582        to->line_start = from->line_start; 
     583        to->line_end = from->line_end; 
     584        to->doc_comment_len = from->doc_comment_len; 
     585        to->doc_comment = from->doc_comment; 
     586        /*??? 
     587           if (from->doc_comment != NULL) { 
     588           to->doc_comment = emalloc(from->doc_comment_len+1); 
     589           memcpy(to->doc_comment, from->doc_comment, from->doc_comment_len+1); 
     590           } 
     591         */ 
     592#else 
     593        to->uses_globals = from->uses_globals; 
     594#endif 
     595        if (from->static_variables) { 
     596                to->static_variables = restore_zval_hash(NULL, from->static_variables); 
     597                to->static_variables->pDestructor = ZVAL_PTR_DTOR; 
    366598#ifndef ZEND_ENGINE_2 
    367                 zend_bool incomplete_class = 0; 
    368                 char *class_name = (char *) zv->value.obj.ce; 
    369                 int name_len = 0; 
    370                 if (!EAG (compress)) { 
    371                     return; 
    372                 } 
    373                 if (class_name != NULL) { 
    374                     zend_class_entry *ce = NULL; 
    375                     name_len = strlen (class_name); 
    376                     if (zend_hash_find(CG (class_table),  
    377                                 (void *) class_name, name_len + 1,  
    378                                 (void **) &ce) != SUCCESS) { 
    379                         char *lowercase_name = 
    380                             estrndup (INCOMPLETE_CLASS, sizeof (INCOMPLETE_CLASS)); 
    381                         zend_str_tolower (lowercase_name, sizeof (INCOMPLETE_CLASS)); 
    382                         if (zend_hash_find(CG (class_table), lowercase_name,  
    383                                     sizeof (INCOMPLETE_CLASS),  
    384                                     (void **) &ce) != SUCCESS) { 
    385                             efree (lowercase_name); 
    386                             zend_error (E_ERROR, "EACCELERATOR can't restore object's class \"%s\"", 
    387                                     class_name); 
    388                         } else { 
    389                             efree (lowercase_name); 
    390                             zv->value.obj.ce = ce; 
    391                             incomplete_class = 1; 
    392                         } 
    393                     } else { 
    394                         zv->value.obj.ce = ce; 
    395                     } 
    396                 } 
    397                 if (zv->value.obj.properties != NULL) { 
    398                     zv->value.obj.properties = 
    399                         restore_zval_hash (NULL, zv->value.obj.properties); 
    400                     zv->value.obj.properties->pDestructor = ZVAL_PTR_DTOR; 
    401                     /* Clearing references */ 
    402                     { 
    403                         Bucket *p = zv->value.obj.properties->pListHead; 
    404                         while (p != NULL) { 
    405                             ((zval *) (p->pDataPtr))->refcount = 1; 
    406                             p = p->pListNext; 
    407                         } 
    408                     } 
    409                 } 
    410                 if (incomplete_class && class_name != NULL) { 
    411                     zval *val; 
    412                     MAKE_STD_ZVAL (val); 
    413                     Z_TYPE_P (val) = IS_STRING; 
    414                     Z_STRVAL_P (val) = estrndup (class_name, name_len); 
    415                     Z_STRLEN_P (val) = name_len; 
    416                     zend_hash_update (Z_OBJPROP_P (zv), MAGIC_MEMBER, 
    417                             sizeof (MAGIC_MEMBER), &val, sizeof (val), 
    418                             NULL); 
    419                 } 
    420 #endif 
    421                 return; 
    422             } 
    423     } 
    424 
    425  
    426 static void call_op_array_ctor_handler (zend_extension * extension, 
    427         zend_op_array * op_array TSRMLS_DC) 
    428 
    429     if (extension->op_array_ctor) { 
    430         extension->op_array_ctor (op_array); 
    431     } 
    432 
    433  
    434 zend_op_array *restore_op_array (zend_op_array * to, 
    435         eaccelerator_op_array * from TSRMLS_DC) 
    436 
    437     zend_function *function; 
    438  
    439 #ifdef ZEND_ENGINE_2 
    440     int fname_len = 0; 
    441     char *fname_lc = NULL; 
    442 #endif 
    443  
    444     ea_debug_pad (EA_DEBUG TSRMLS_CC); 
    445     ea_debug_printf (EA_DEBUG, "[%d] restore_op_array: %s\n", getpid (), 
    446             from->function_name ? from->function_name : "(top)"); 
    447  
    448     if (from->type == ZEND_INTERNAL_FUNCTION) { 
    449         if (to == NULL) { 
    450             to = emalloc (sizeof (zend_internal_function)); 
    451         } 
    452         memset (to, 0, sizeof (zend_internal_function)); 
    453     } else { 
    454         if (to == NULL) { 
    455             to = emalloc (sizeof (zend_op_array)); 
    456         } 
    457         memset (to, 0, sizeof (zend_op_array)); 
    458         if (ZendOptimizer) { 
    459             zend_llist_apply_with_argument (&zend_extensions, 
    460                     (llist_apply_with_arg_func_t) call_op_array_ctor_handler, 
    461                     to TSRMLS_CC); 
    462         } 
    463     } 
    464     to->type = from->type; 
    465 #ifdef ZEND_ENGINE_2 
    466     /* this is internal function's case 
    467      * struct zend_internal_function 
    468      zend_uchar type; 
    469      char *function_name;      
    470      zend_class_entry *scope; 
    471      zend_uint fn_flags;   
    472      union _zend_function *prototype; 
    473      zend_uint num_args; 
    474      zend_uint required_num_args; 
    475      zend_arg_info *arg_info; 
    476      zend_bool pass_rest_by_reference; 
    477      unsigned char return_reference; 
    478      */ 
    479     /* 
    480