PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/opcache - zend_accelerator_util_funcs.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 332 533 62.3 %
Date: 2014-08-04 Functions: 24 25 96.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend OPcache                                                         |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Zeev Suraski <zeev@zend.com>                                |
      17             :    |          Stanislav Malyshev <stas@zend.com>                          |
      18             :    |          Dmitry Stogov <dmitry@zend.com>                             |
      19             :    +----------------------------------------------------------------------+
      20             : */
      21             : 
      22             : #include "zend_API.h"
      23             : #include "zend_constants.h"
      24             : #include "zend_accelerator_util_funcs.h"
      25             : #include "zend_persist.h"
      26             : #include "zend_shared_alloc.h"
      27             : 
      28             : #define ZEND_PROTECTED_REFCOUNT (1<<30)
      29             : 
      30             : static zend_uint zend_accel_refcount = ZEND_PROTECTED_REFCOUNT;
      31             : 
      32             : #if SIZEOF_SIZE_T <= SIZEOF_LONG
      33             : /* If sizeof(void*) == sizeof(ulong) we can use zend_hash index functions */
      34             : # define accel_xlat_set(old, new)       zend_hash_index_update(&ZCG(bind_hash), (ulong)(zend_uintptr_t)(old), &(new), sizeof(void*), NULL)
      35             : # define accel_xlat_get(old, new)       zend_hash_index_find(&ZCG(bind_hash), (ulong)(zend_uintptr_t)(old), (void**)&(new))
      36             : #else
      37             : # define accel_xlat_set(old, new)       zend_hash_quick_add(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (ulong)(zend_uintptr_t)(old), (void**)&(new), sizeof(void*), NULL)
      38             : # define accel_xlat_get(old, new)       zend_hash_quick_find(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (ulong)(zend_uintptr_t)(old), (void**)&(new))
      39             : #endif
      40             : 
      41             : typedef int (*id_function_t)(void *, void *);
      42             : typedef void (*unique_copy_ctor_func_t)(void *pElement);
      43             : 
      44             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
      45             : static const Bucket *uninitialized_bucket = NULL;
      46             : #endif
      47             : 
      48             : static int zend_prepare_function_for_execution(zend_op_array *op_array);
      49             : static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind);
      50             : 
      51          14 : static void zend_accel_destroy_zend_function(zend_function *function)
      52             : {
      53             :         TSRMLS_FETCH();
      54             : 
      55          14 :         if (function->type == ZEND_USER_FUNCTION) {
      56          14 :                 if (function->op_array.static_variables) {
      57             : 
      58           0 :                         efree(function->op_array.static_variables);
      59           0 :                         function->op_array.static_variables = NULL;
      60             :                 }
      61             :         }
      62             : 
      63          14 :         destroy_zend_function(function TSRMLS_CC);
      64          14 : }
      65             : 
      66           1 : static void zend_accel_destroy_zend_class(zend_class_entry **pce)
      67             : {
      68           1 :         zend_class_entry *ce = *pce;
      69             : 
      70           1 :         ce->function_table.pDestructor = (dtor_func_t) zend_accel_destroy_zend_function;
      71           1 :         destroy_zend_class(pce);
      72           1 : }
      73             : 
      74         423 : zend_persistent_script* create_persistent_script(void)
      75             : {
      76         423 :         zend_persistent_script *persistent_script = (zend_persistent_script *) emalloc(sizeof(zend_persistent_script));
      77         423 :         memset(persistent_script, 0, sizeof(zend_persistent_script));
      78             : 
      79         423 :         zend_hash_init(&persistent_script->function_table, 100, NULL, (dtor_func_t) zend_accel_destroy_zend_function, 0);
      80             :         /* class_table is usually destroyed by free_persistent_script() that
      81             :          * overrides destructor. ZEND_CLASS_DTOR may be used by standard
      82             :          * PHP compiler
      83             :          */
      84         423 :         zend_hash_init(&persistent_script->class_table, 10, NULL, ZEND_CLASS_DTOR, 0);
      85             : 
      86         423 :         return persistent_script;
      87             : }
      88             : 
      89         844 : static int compact_hash_table(HashTable *ht)
      90             : {
      91         844 :         uint i = 3;
      92             :         uint nSize;
      93             :         Bucket **t;
      94             : 
      95         844 :         if (!ht->nNumOfElements) {
      96             :                 /* Empty tables don't allocate space for Buckets */
      97         819 :                 return 1;
      98             :         }
      99             : 
     100          25 :         if (ht->nNumOfElements >= 0x80000000) {
     101             :                 /* prevent overflow */
     102           0 :                 nSize = 0x80000000;
     103             :         } else {
     104          50 :                 while ((1U << i) < ht->nNumOfElements) {
     105           0 :                         i++;
     106             :                 }
     107          25 :                 nSize = 1 << i;
     108             :         }
     109             : 
     110          25 :         if (nSize >= ht->nTableSize) {
     111             :                 /* Keep the size */
     112           0 :                 return 1;
     113             :         }
     114             : 
     115          25 :         t = (Bucket **)pemalloc(nSize * sizeof(Bucket *), ht->persistent);
     116          25 :         if (!t) {
     117           0 :                 return 0;
     118             :         }
     119             : 
     120          25 :         pefree(ht->arBuckets, ht->persistent);
     121             : 
     122          25 :         ht->arBuckets = t;
     123          25 :         ht->nTableSize = nSize;
     124          25 :         ht->nTableMask = ht->nTableSize - 1;
     125          25 :         zend_hash_rehash(ht);
     126             :         
     127          25 :         return 1;
     128             : }
     129             : 
     130         422 : int compact_persistent_script(zend_persistent_script *persistent_script)
     131             : {
     132         844 :         return compact_hash_table(&persistent_script->function_table) &&
     133         422 :                compact_hash_table(&persistent_script->class_table);
     134             : }
     135             : 
     136           1 : void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements)
     137             : {
     138           1 :         if (destroy_elements) {
     139           1 :                 persistent_script->function_table.pDestructor = (dtor_func_t)zend_accel_destroy_zend_function;
     140           1 :                 persistent_script->class_table.pDestructor = (dtor_func_t)zend_accel_destroy_zend_class;
     141             :         } else {
     142           0 :                 persistent_script->function_table.pDestructor = NULL;
     143           0 :                 persistent_script->class_table.pDestructor = NULL;
     144             :         }
     145             : 
     146           1 :         zend_hash_destroy(&persistent_script->function_table);
     147           1 :         zend_hash_destroy(&persistent_script->class_table);
     148             : 
     149           1 :         if (persistent_script->full_path) {
     150           0 :                 efree(persistent_script->full_path);
     151             :         }
     152             : 
     153           1 :         efree(persistent_script);
     154           1 : }
     155             : 
     156        2391 : static int is_not_internal_function(zend_function *function)
     157             : {
     158        2391 :         return(function->type != ZEND_INTERNAL_FUNCTION);
     159             : }
     160             : 
     161           1 : void zend_accel_free_user_functions(HashTable *ht TSRMLS_DC)
     162             : {
     163           1 :         dtor_func_t orig_dtor = ht->pDestructor;
     164             : 
     165           1 :         ht->pDestructor = NULL;
     166           1 :         zend_hash_apply(ht, (apply_func_t) is_not_internal_function TSRMLS_CC);
     167           1 :         ht->pDestructor = orig_dtor;
     168           1 : }
     169             : 
     170     1009018 : static int move_user_function(zend_function *function
     171             : #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
     172             :         TSRMLS_DC 
     173             : #endif
     174             :         , int num_args, va_list args, zend_hash_key *hash_key) 
     175             : {
     176     1009018 :         HashTable *function_table = va_arg(args, HashTable *);
     177             :         (void)num_args; /* keep the compiler happy */
     178             : #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
     179             :         TSRMLS_FETCH();
     180             : #endif 
     181             : 
     182     1009018 :         if (function->type == ZEND_USER_FUNCTION) {
     183          24 :                 zend_hash_quick_update(function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, function, sizeof(zend_function), NULL);
     184          24 :                 return 1;
     185             :         } else {
     186     1008994 :                 return 0;
     187             :         }
     188             : }
     189             : 
     190         422 : void zend_accel_move_user_functions(HashTable *src, HashTable *dst TSRMLS_DC)
     191             : {
     192         422 :         dtor_func_t orig_dtor = src->pDestructor;
     193             : 
     194         422 :         src->pDestructor = NULL;
     195             : #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
     196             :         zend_hash_apply_with_arguments(src, (apply_func_args_t)move_user_function, 1, dst);
     197             : #else
     198         422 :         zend_hash_apply_with_arguments(src TSRMLS_CC, (apply_func_args_t)move_user_function, 1, dst);
     199             : #endif 
     200         422 :         src->pDestructor = orig_dtor;
     201         422 : }
     202             : 
     203    50481740 : static int copy_internal_function(zend_function *function, HashTable *function_table TSRMLS_DC)
     204             : {
     205    50481740 :         if (function->type == ZEND_INTERNAL_FUNCTION) {
     206    50481740 :                 zend_hash_update(function_table, function->common.function_name, strlen(function->common.function_name) + 1, function, sizeof(zend_function), NULL);
     207             :         }
     208    50481740 :         return 0;
     209             : }
     210             : 
     211       21148 : void zend_accel_copy_internal_functions(TSRMLS_D)
     212             : {
     213       21148 :         zend_hash_apply_with_argument(CG(function_table), (apply_func_arg_t)copy_internal_function, &ZCG(function_table) TSRMLS_CC);
     214       21148 :         ZCG(internal_functions_count) = zend_hash_num_elements(&ZCG(function_table));
     215       21148 : }
     216             : 
     217           2 : static void zend_destroy_property_info(zend_property_info *property_info)
     218             : {
     219           2 :         interned_efree((char*)property_info->name);
     220           2 :         if (property_info->doc_comment) {
     221           0 :                 efree((char*)property_info->doc_comment);
     222             :         }
     223           2 : }
     224             : 
     225             : #if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
     226           0 : static zend_ast *zend_ast_clone(zend_ast *ast TSRMLS_DC)
     227             : {
     228             :         int i;
     229             :         zend_ast *node;
     230             : 
     231           0 :         if (ast->kind == ZEND_CONST) {
     232           0 :                 node = emalloc(sizeof(zend_ast) + sizeof(zval));
     233           0 :                 node->kind = ZEND_CONST;
     234           0 :                 node->children = 0;
     235           0 :                 node->u.val = (zval*)(node + 1);
     236           0 :                 *node->u.val = *ast->u.val;
     237           0 :                 if ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) {
     238           0 :                         switch ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK)) {
     239             :                                 case IS_STRING:
     240             :                                 case IS_CONSTANT:
     241           0 :                                         Z_STRVAL_P(node->u.val) = (char *) interned_estrndup(Z_STRVAL_P(ast->u.val), Z_STRLEN_P(ast->u.val));
     242           0 :                                         break;
     243             :                                 case IS_ARRAY:
     244             : #if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
     245             :                                 case IS_CONSTANT_ARRAY:
     246             : #endif
     247           0 :                                         if (ast->u.val->value.ht && ast->u.val->value.ht != &EG(symbol_table)) {
     248           0 :                                                 ALLOC_HASHTABLE(node->u.val->value.ht);
     249           0 :                                                 zend_hash_clone_zval(node->u.val->value.ht, ast->u.val->value.ht, 0);
     250             :                                         }
     251           0 :                                         break;
     252             :                                 case IS_CONSTANT_AST:
     253           0 :                                         Z_AST_P(node->u.val) = zend_ast_clone(Z_AST_P(ast->u.val) TSRMLS_CC);
     254             :                                         break;
     255             :                         }
     256             :                 }
     257             :         } else {
     258           0 :                 node = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
     259           0 :                 node->kind = ast->kind;
     260           0 :                 node->children = ast->children;
     261           0 :                 for (i = 0; i < ast->children; i++) {
     262           0 :                         if ((&ast->u.child)[i]) {
     263           0 :                                 (&node->u.child)[i] = zend_ast_clone((&ast->u.child)[i] TSRMLS_CC);
     264             :                         } else {
     265           0 :                                 (&node->u.child)[i] = NULL;
     266             :                         }
     267             :                 }
     268             :         }
     269           0 :         return node;
     270             : }
     271             : #endif
     272             : 
     273           2 : static inline zval* zend_clone_zval(zval *src, int bind TSRMLS_DC)
     274             : {
     275           2 :         zval *ret, **ret_ptr = NULL;
     276             : 
     277           2 :         if (!bind) {
     278           0 :                 ALLOC_ZVAL(ret);
     279           0 :                 *ret = *src;
     280           0 :                 INIT_PZVAL(ret);
     281           2 :         } else if (Z_REFCOUNT_P(src) == 1) {
     282           2 :                 ALLOC_ZVAL(ret);
     283           2 :                 *ret = *src;
     284           0 :         } else if (accel_xlat_get(src, ret_ptr) != SUCCESS) {
     285           0 :                 ALLOC_ZVAL(ret);
     286           0 :                 *ret = *src;
     287           0 :                 accel_xlat_set(src, ret);
     288             :         } else {
     289           0 :                 return *ret_ptr;
     290             :         }
     291             : 
     292             : #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
     293           2 :         if ((Z_TYPE_P(ret) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) {
     294           0 :                 switch ((Z_TYPE_P(ret) & IS_CONSTANT_TYPE_MASK)) {
     295             : #else
     296             :         if ((Z_TYPE_P(ret) & ~IS_CONSTANT_INDEX) >= IS_ARRAY) {
     297             :                 switch ((Z_TYPE_P(ret) & ~IS_CONSTANT_INDEX)) {
     298             : #endif
     299             :                         case IS_STRING:
     300             :                         case IS_CONSTANT:
     301           0 :                                 Z_STRVAL_P(ret) = (char *) interned_estrndup(Z_STRVAL_P(ret), Z_STRLEN_P(ret));
     302           0 :                                 break;
     303             :                         case IS_ARRAY:
     304             : #if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
     305             :                         case IS_CONSTANT_ARRAY:
     306             : #endif
     307           0 :                                 if (ret->value.ht && ret->value.ht != &EG(symbol_table)) {
     308           0 :                                         ALLOC_HASHTABLE(ret->value.ht);
     309           0 :                                         zend_hash_clone_zval(ret->value.ht, src->value.ht, 0);
     310             :                                 }
     311           0 :                                 break;
     312             : #if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
     313             :                         case IS_CONSTANT_AST:
     314           0 :                                 Z_AST_P(ret) = zend_ast_clone(Z_AST_P(ret) TSRMLS_CC);
     315             :                                 break;
     316             : #endif
     317             :                 }
     318             :         }
     319           2 :         return ret;
     320             : }
     321             : 
     322          26 : static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
     323             : {
     324             :         Bucket *p, *q, **prev;
     325             :         ulong nIndex;
     326             :         zval *ppz;
     327             :         TSRMLS_FETCH();
     328             : 
     329          26 :         ht->nTableSize = source->nTableSize;
     330          26 :         ht->nTableMask = source->nTableMask;
     331          26 :         ht->nNumOfElements = source->nNumOfElements;
     332          26 :         ht->nNextFreeElement = source->nNextFreeElement;
     333          26 :         ht->pDestructor = ZVAL_PTR_DTOR;
     334             : #if ZEND_DEBUG
     335             :         ht->inconsistent = 0;
     336             : #endif
     337          26 :         ht->persistent = 0;
     338          26 :         ht->arBuckets = NULL;
     339          26 :         ht->pListHead = NULL;
     340          26 :         ht->pListTail = NULL;
     341          26 :         ht->pInternalPointer = NULL;
     342          26 :         ht->nApplyCount = 0;
     343          26 :         ht->bApplyProtection = 1;
     344             : 
     345             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     346          26 :         if (!ht->nTableMask) {
     347           0 :                 ht->arBuckets = (Bucket**)&uninitialized_bucket;
     348           0 :                 return;
     349             :         }
     350             : #endif
     351             : 
     352          26 :         ht->arBuckets = (Bucket **) ecalloc(ht->nTableSize, sizeof(Bucket *));
     353             : 
     354          26 :         prev = &ht->pListHead;
     355          26 :         p = source->pListHead;
     356          82 :         while (p) {
     357          30 :                 nIndex = p->h & ht->nTableMask;
     358             : 
     359             :                 /* Create bucket and initialize key */
     360             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     361          30 :                 if (!p->nKeyLength) {
     362           0 :                         q = (Bucket *) emalloc(sizeof(Bucket));
     363           0 :                         q->arKey = NULL;
     364          60 :                 } else if (IS_INTERNED(p->arKey)) {
     365          30 :                         q = (Bucket *) emalloc(sizeof(Bucket));
     366          30 :                         q->arKey = p->arKey;
     367             :                 } else {
     368           0 :                         q = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength);
     369           0 :                         q->arKey = ((char*)q) + sizeof(Bucket);
     370           0 :                         memcpy((char*)q->arKey, p->arKey, p->nKeyLength);
     371             :                 }
     372             : #else
     373             :                 q = (Bucket *) emalloc(sizeof(Bucket) - 1 + p->nKeyLength);
     374             :                 if (p->nKeyLength) {
     375             :                         memcpy(q->arKey, p->arKey, p->nKeyLength);
     376             :                 }
     377             : #endif
     378          30 :                 q->h = p->h;
     379          30 :                 q->nKeyLength = p->nKeyLength;
     380             : 
     381             :                 /* Insert into hash collision list */
     382          30 :                 q->pNext = ht->arBuckets[nIndex];
     383          30 :                 q->pLast = NULL;
     384          30 :                 if (q->pNext) {
     385           1 :                         q->pNext->pLast = q;
     386             :                 }
     387          30 :                 ht->arBuckets[nIndex] = q;
     388             : 
     389             :                 /* Insert into global list */
     390          30 :                 q->pListLast = ht->pListTail;
     391          30 :                 ht->pListTail = q;
     392          30 :                 q->pListNext = NULL;
     393          30 :                 *prev = q;
     394          30 :                 prev = &q->pListNext;
     395             : 
     396             :                 /* Copy data */
     397          30 :                 q->pData = &q->pDataPtr;
     398          30 :                 if (!bind) {
     399          30 :                         ALLOC_ZVAL(ppz);
     400          30 :                         *ppz = *((zval*)p->pDataPtr);
     401          30 :                         INIT_PZVAL(ppz);
     402           0 :                 } else if (Z_REFCOUNT_P((zval*)p->pDataPtr) == 1) {
     403           0 :                         ALLOC_ZVAL(ppz);
     404           0 :                         *ppz = *((zval*)p->pDataPtr);
     405           0 :                 } else if (accel_xlat_get(p->pDataPtr, ppz) != SUCCESS) {
     406           0 :                         ALLOC_ZVAL(ppz);
     407           0 :                         *ppz = *((zval*)p->pDataPtr);
     408           0 :                         accel_xlat_set(p->pDataPtr, ppz);
     409             :                 } else {
     410           0 :                         q->pDataPtr = *(void**)ppz;
     411           0 :                         p = p->pListNext;
     412           0 :                         continue;
     413             :                 }
     414          30 :                 q->pDataPtr = (void*)ppz;
     415             : 
     416             : #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
     417          30 :                 if ((Z_TYPE_P((zval*)p->pDataPtr) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) {
     418          21 :                         switch ((Z_TYPE_P((zval*)p->pDataPtr) & IS_CONSTANT_TYPE_MASK)) {
     419             : #else
     420             :                 if ((Z_TYPE_P((zval*)p->pDataPtr) & ~IS_CONSTANT_INDEX) >= IS_ARRAY) {
     421             :                         switch ((Z_TYPE_P((zval*)p->pDataPtr) & ~IS_CONSTANT_INDEX)) {
     422             : #endif
     423             :                                 case IS_STRING:
     424             :                                 case IS_CONSTANT:
     425           9 :                                         Z_STRVAL_P(ppz) = (char *) interned_estrndup(Z_STRVAL_P((zval*)p->pDataPtr), Z_STRLEN_P((zval*)p->pDataPtr));
     426           9 :                                         break;
     427             :                                 case IS_ARRAY:
     428             : #if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
     429             :                                 case IS_CONSTANT_ARRAY:
     430             : #endif
     431          12 :                                         if (((zval*)p->pDataPtr)->value.ht && ((zval*)p->pDataPtr)->value.ht != &EG(symbol_table)) {
     432          12 :                                                 ALLOC_HASHTABLE(ppz->value.ht);
     433          12 :                                                 zend_hash_clone_zval(ppz->value.ht, ((zval*)p->pDataPtr)->value.ht, 0);
     434             :                                         }
     435          12 :                                         break;
     436             : #if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
     437             :                                 case IS_CONSTANT_AST:
     438           0 :                                         Z_AST_P(ppz) = zend_ast_clone(Z_AST_P(ppz) TSRMLS_CC);
     439             :                                         break;
     440             : #endif
     441             :                         }
     442             :                 }
     443             : 
     444          30 :                 p = p->pListNext;
     445             :         }
     446          26 :         ht->pInternalPointer = ht->pListHead;
     447             : }
     448             : 
     449           1 : static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce TSRMLS_DC)
     450             : {
     451             :         Bucket *p, *q, **prev;
     452             :         ulong nIndex;
     453             :         zend_class_entry **new_ce;
     454             :         zend_function** new_prototype;
     455             :         zend_op_array *new_entry;
     456             : 
     457           1 :         ht->nTableSize = source->nTableSize;
     458           1 :         ht->nTableMask = source->nTableMask;
     459           1 :         ht->nNumOfElements = source->nNumOfElements;
     460           1 :         ht->nNextFreeElement = source->nNextFreeElement;
     461           1 :         ht->pDestructor = ZEND_FUNCTION_DTOR;
     462             : #if ZEND_DEBUG
     463             :         ht->inconsistent = 0;
     464             : #endif
     465           1 :         ht->persistent = 0;
     466           1 :         ht->pListHead = NULL;
     467           1 :         ht->pListTail = NULL;
     468           1 :         ht->pInternalPointer = NULL;
     469           1 :         ht->nApplyCount = 0;
     470           1 :         ht->bApplyProtection = 1;
     471             : 
     472             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     473           1 :         if (!ht->nTableMask) {
     474           0 :                 ht->arBuckets = (Bucket**)&uninitialized_bucket;
     475           0 :                 return;
     476             :         }
     477             : #endif
     478             : 
     479           1 :         ht->arBuckets = (Bucket **) ecalloc(ht->nTableSize, sizeof(Bucket *));
     480             : 
     481           1 :         prev = &ht->pListHead;
     482           1 :         p = source->pListHead;
     483           7 :         while (p) {
     484           5 :                 nIndex = p->h & ht->nTableMask;
     485             : 
     486             :                 /* Create bucket and initialize key */
     487             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     488           5 :                 if (!p->nKeyLength) {
     489           0 :                         q = (Bucket *) emalloc(sizeof(Bucket));
     490           0 :                         q->arKey = NULL;
     491          10 :                 } else if (IS_INTERNED(p->arKey)) {
     492           5 :                         q = (Bucket *) emalloc(sizeof(Bucket));
     493           5 :                         q->arKey = p->arKey;
     494             :                 } else {
     495           0 :                         q = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength);
     496           0 :                         q->arKey = ((char*)q) + sizeof(Bucket);
     497           0 :                         memcpy((char*)q->arKey, p->arKey, p->nKeyLength);
     498             :                 }
     499             : #else
     500             :                 q = (Bucket *) emalloc(sizeof(Bucket) - 1 + p->nKeyLength);
     501             :                 if (p->nKeyLength) {
     502             :                         memcpy(q->arKey, p->arKey, p->nKeyLength);
     503             :                 }
     504             : #endif
     505           5 :                 q->h = p->h;
     506           5 :                 q->nKeyLength = p->nKeyLength;
     507             : 
     508             :                 /* Insert into hash collision list */
     509           5 :                 q->pNext = ht->arBuckets[nIndex];
     510           5 :                 q->pLast = NULL;
     511           5 :                 if (q->pNext) {
     512           1 :                         q->pNext->pLast = q;
     513             :                 }
     514           5 :                 ht->arBuckets[nIndex] = q;
     515             : 
     516             :                 /* Insert into global list */
     517           5 :                 q->pListLast = ht->pListTail;
     518           5 :                 ht->pListTail = q;
     519           5 :                 q->pListNext = NULL;
     520           5 :                 *prev = q;
     521           5 :                 prev = &q->pListNext;
     522             : 
     523             :                 /* Copy data */
     524           5 :                 q->pData = (void *) emalloc(sizeof(zend_function));
     525           5 :                 new_entry = (zend_op_array*)q->pData;
     526           5 :                 *new_entry = *(zend_op_array*)p->pData;
     527           5 :                 q->pDataPtr = NULL;
     528             : 
     529             :                 /* Copy constructor */
     530             :                 /* we use refcount to show that op_array is referenced from several places */
     531           5 :                 if (new_entry->refcount != NULL) {
     532           0 :                         accel_xlat_set(p->pData, new_entry);
     533             :                 }
     534             : 
     535           5 :                 zend_prepare_function_for_execution(new_entry);
     536             : 
     537           5 :                 if (old_ce == new_entry->scope) {
     538           5 :                         new_entry->scope = ce;
     539             :                 } else {
     540           0 :                         if (accel_xlat_get(new_entry->scope, new_ce) == SUCCESS) {
     541           0 :                                 new_entry->scope = *new_ce;
     542             :                         } else {
     543           0 :                                 zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name, new_entry->function_name);
     544             :                         }
     545             :                 }
     546             : 
     547             :                 /* update prototype */
     548           5 :                 if (new_entry->prototype) {
     549           0 :                         if (accel_xlat_get(new_entry->prototype, new_prototype) == SUCCESS) {
     550           0 :                                 new_entry->prototype = *new_prototype;
     551             :                         } else {
     552           0 :                                 zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name, new_entry->function_name);
     553             :                         }
     554             :                 }
     555             : 
     556           5 :                 p = p->pListNext;
     557             :         }
     558           1 :         ht->pInternalPointer = ht->pListHead;
     559             : }
     560             : 
     561           1 : static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce TSRMLS_DC)
     562             : {
     563             :         Bucket *p, *q, **prev;
     564             :         ulong nIndex;
     565             :         zend_class_entry **new_ce;
     566             :         zend_property_info *prop_info;
     567             : 
     568           1 :         ht->nTableSize = source->nTableSize;
     569           1 :         ht->nTableMask = source->nTableMask;
     570           1 :         ht->nNumOfElements = source->nNumOfElements;
     571           1 :         ht->nNextFreeElement = source->nNextFreeElement;
     572           1 :         ht->pDestructor = (dtor_func_t) zend_destroy_property_info;
     573             : #if ZEND_DEBUG
     574             :         ht->inconsistent = 0;
     575             : #endif
     576           1 :         ht->persistent = 0;
     577           1 :         ht->pListHead = NULL;
     578           1 :         ht->pListTail = NULL;
     579           1 :         ht->pInternalPointer = NULL;
     580           1 :         ht->nApplyCount = 0;
     581           1 :         ht->bApplyProtection = 1;
     582             : 
     583             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     584           1 :         if (!ht->nTableMask) {
     585           0 :                 ht->arBuckets = (Bucket**)&uninitialized_bucket;
     586           0 :                 return;
     587             :         }
     588             : #endif
     589             : 
     590           1 :         ht->arBuckets = (Bucket **) ecalloc(ht->nTableSize, sizeof(Bucket *));
     591             : 
     592           1 :         prev = &ht->pListHead;
     593           1 :         p = source->pListHead;
     594           4 :         while (p) {
     595           2 :                 nIndex = p->h & ht->nTableMask;
     596             : 
     597             :                 /* Create bucket and initialize key */
     598             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     599           2 :                 if (!p->nKeyLength) {
     600           0 :                         q = (Bucket *) emalloc(sizeof(Bucket));
     601           0 :                         q->arKey = NULL;
     602           4 :                 } else if (IS_INTERNED(p->arKey)) {
     603           2 :                         q = (Bucket *) emalloc(sizeof(Bucket));
     604           2 :                         q->arKey = p->arKey;
     605             :                 } else {
     606           0 :                         q = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength);
     607           0 :                         q->arKey = ((char*)q) + sizeof(Bucket);
     608           0 :                         memcpy((char*)q->arKey, p->arKey, p->nKeyLength);
     609             :                 }
     610             : #else
     611             :                 q = (Bucket *) emalloc(sizeof(Bucket) - 1 + p->nKeyLength);
     612             :                 if (p->nKeyLength) {
     613             :                         memcpy(q->arKey, p->arKey, p->nKeyLength);
     614             :                 }
     615             : #endif
     616           2 :                 q->h = p->h;
     617           2 :                 q->nKeyLength = p->nKeyLength;
     618             : 
     619             :                 /* Insert into hash collision list */
     620           2 :                 q->pNext = ht->arBuckets[nIndex];
     621           2 :                 q->pLast = NULL;
     622           2 :                 if (q->pNext) {
     623           0 :                         q->pNext->pLast = q;
     624             :                 }
     625           2 :                 ht->arBuckets[nIndex] = q;
     626             : 
     627             :                 /* Insert into global list */
     628           2 :                 q->pListLast = ht->pListTail;
     629           2 :                 ht->pListTail = q;
     630           2 :                 q->pListNext = NULL;
     631           2 :                 *prev = q;
     632           2 :                 prev = &q->pListNext;
     633             : 
     634             :                 /* Copy data */
     635           2 :                 q->pData = (void *) emalloc(sizeof(zend_property_info));
     636           2 :                 prop_info = q->pData;
     637           2 :                 *prop_info = *(zend_property_info*)p->pData;
     638           2 :                 q->pDataPtr = NULL;
     639             : 
     640             :                 /* Copy constructor */
     641           2 :                 prop_info->name = interned_estrndup(prop_info->name, prop_info->name_length);
     642           2 :                 if (prop_info->doc_comment) {
     643           0 :                         if (ZCG(accel_directives).load_comments) {
     644           0 :                                 prop_info->doc_comment = estrndup(prop_info->doc_comment, prop_info->doc_comment_len);
     645             :                         } else {
     646           0 :                                 prop_info->doc_comment = NULL;
     647             :                         }
     648             :                 }
     649           2 :                 if (prop_info->ce == old_ce) {
     650           2 :                         prop_info->ce = ce;
     651           0 :                 } else if (accel_xlat_get(prop_info->ce, new_ce) == SUCCESS) {
     652           0 :                         prop_info->ce = *new_ce;
     653             :                 } else {
     654           0 :                         zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s, property %s", ce->name, prop_info->name);
     655             :                 }
     656             : 
     657           2 :                 p = p->pListNext;
     658             :         }
     659           1 :         ht->pInternalPointer = ht->pListHead;
     660             : }
     661             : 
     662             : /* protects reference count, creates copy of statics */
     663         451 : static int zend_prepare_function_for_execution(zend_op_array *op_array)
     664             : {
     665         451 :         HashTable *shared_statics = op_array->static_variables;
     666             : 
     667             :         /* protect reference count */
     668         451 :         op_array->refcount = &zend_accel_refcount;
     669         451 :         (*op_array->refcount) = ZEND_PROTECTED_REFCOUNT;
     670             : 
     671             :         /* copy statics */
     672         451 :         if (shared_statics) {
     673          13 :                 ALLOC_HASHTABLE(op_array->static_variables);
     674          13 :                 zend_hash_clone_zval(op_array->static_variables, shared_statics, 0);
     675             :         }
     676             : 
     677         451 :         return 0;
     678             : }
     679             : 
     680             : #define zend_update_inherited_handler(handler) \
     681             : { \
     682             :         if (ce->handler != NULL) { \
     683             :                 if (accel_xlat_get(ce->handler, new_func) == SUCCESS) { \
     684             :                         ce->handler = *new_func; \
     685             :                 } else { \
     686             :                         zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s", ce->name); \
     687             :                 } \
     688             :         } \
     689             : }
     690             : 
     691             : /* Protects class' refcount, copies default properties, functions and class name */
     692           1 : static void zend_class_copy_ctor(zend_class_entry **pce)
     693             : {
     694           1 :         zend_class_entry *ce = *pce;
     695           1 :         zend_class_entry *old_ce = ce;
     696             :         zend_class_entry **new_ce;
     697             :         zend_function **new_func;
     698             :         TSRMLS_FETCH();
     699             : 
     700           1 :         *pce = ce = emalloc(sizeof(zend_class_entry));
     701           1 :         *ce = *old_ce;
     702           1 :         ce->refcount = 1;
     703             : 
     704           1 :         if (old_ce->refcount != 1) {
     705             :                 /* this class is not used as a parent for any other classes */
     706           0 :                 accel_xlat_set(old_ce, ce);
     707             :         }
     708             : 
     709             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     710           1 :         if (old_ce->default_properties_table) {
     711             :                 int i;
     712             : 
     713           0 :                 ce->default_properties_table = emalloc(sizeof(zval*) * old_ce->default_properties_count);
     714           0 :                 for (i = 0; i < old_ce->default_properties_count; i++) {
     715           0 :                         if (old_ce->default_properties_table[i]) {
     716           0 :                                 ce->default_properties_table[i] = zend_clone_zval(old_ce->default_properties_table[i], 0 TSRMLS_CC);
     717             :                         } else {
     718           0 :                                 ce->default_properties_table[i] = NULL;
     719             :                         }
     720             :                 }
     721             :         }
     722             : #else
     723             :         zend_hash_clone_zval(&ce->default_properties, &old_ce->default_properties, 0);
     724             : #endif
     725             : 
     726           1 :         zend_hash_clone_methods(&ce->function_table, &old_ce->function_table, old_ce, ce TSRMLS_CC);
     727             : 
     728             :         /* static members */
     729             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     730           1 :         if (old_ce->default_static_members_table) {
     731             :                 int i;
     732             : 
     733           1 :                 ce->default_static_members_table = emalloc(sizeof(zval*) * old_ce->default_static_members_count);
     734           3 :                 for (i = 0; i < old_ce->default_static_members_count; i++) {
     735           2 :                         if (old_ce->default_static_members_table[i]) {
     736           2 :                                 ce->default_static_members_table[i] = zend_clone_zval(old_ce->default_static_members_table[i], 1 TSRMLS_CC);
     737             :                         } else {
     738           0 :                                 ce->default_static_members_table[i] = NULL;
     739             :                         }
     740             :                 }
     741             :         }
     742           1 :         ce->static_members_table = ce->default_static_members_table;
     743             : #else
     744             :         zend_hash_clone_zval(&ce->default_static_members, &old_ce->default_static_members, 1);
     745             :         ce->static_members = &ce->default_static_members;
     746             : #endif
     747             : 
     748             :         /* properties_info */
     749           1 :         zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce, ce TSRMLS_CC);
     750             : 
     751             :         /* constants table */
     752           1 :         zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 0);
     753             : 
     754           1 :         ce->name = interned_estrndup(ce->name, ce->name_length);
     755             : 
     756             :         /* interfaces aren't really implemented, so we create a new table */
     757           1 :         if (ce->num_interfaces) {
     758           0 :                 ce->interfaces = emalloc(sizeof(zend_class_entry *) * ce->num_interfaces);
     759           0 :                 memset(ce->interfaces, 0, sizeof(zend_class_entry *) * ce->num_interfaces);
     760             :         } else {
     761           1 :                 ce->interfaces = NULL;
     762             :         }
     763           1 :         if (ZEND_CE_DOC_COMMENT(ce)) {
     764           0 :                 if (ZCG(accel_directives).load_comments) {
     765           0 :                         ZEND_CE_DOC_COMMENT(ce) = estrndup(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce));
     766             :                 } else {
     767           0 :                         ZEND_CE_DOC_COMMENT(ce) =  NULL;
     768             :                 }
     769             :         }
     770             : 
     771           1 :         if (ce->parent) {
     772           0 :                 if (accel_xlat_get(ce->parent, new_ce) == SUCCESS) {
     773           0 :                         ce->parent = *new_ce;
     774             :                 } else {
     775           0 :                         zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s", ce->name);
     776             :                 }
     777             :         }
     778             : 
     779           1 :         zend_update_inherited_handler(constructor);
     780           1 :         zend_update_inherited_handler(destructor);
     781           1 :         zend_update_inherited_handler(clone);
     782           1 :         zend_update_inherited_handler(__get);
     783           1 :         zend_update_inherited_handler(__set);
     784           1 :         zend_update_inherited_handler(__call);
     785             : /* 5.1 stuff */
     786           1 :         zend_update_inherited_handler(serialize_func);
     787           1 :         zend_update_inherited_handler(unserialize_func);
     788           1 :         zend_update_inherited_handler(__isset);
     789           1 :         zend_update_inherited_handler(__unset);
     790             : /* 5.2 stuff */
     791           1 :         zend_update_inherited_handler(__tostring);
     792             : 
     793             : #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
     794             : /* 5.3 stuff */
     795           1 :         zend_update_inherited_handler(__callstatic);
     796             : #endif
     797             : 
     798             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     799             : /* 5.4 traits */
     800           1 :         if (ce->trait_aliases) {
     801             :                 zend_trait_alias **trait_aliases;
     802           0 :                 int i = 0;
     803             : 
     804           0 :                 while (ce->trait_aliases[i]) {
     805           0 :                         i++;
     806             :                 }
     807           0 :                 trait_aliases = emalloc(sizeof(zend_trait_alias*) * (i + 1));
     808           0 :                 i = 0;
     809           0 :                 while (ce->trait_aliases[i]) {
     810           0 :                         trait_aliases[i] = emalloc(sizeof(zend_trait_alias));
     811           0 :                         memcpy(trait_aliases[i], ce->trait_aliases[i], sizeof(zend_trait_alias));
     812           0 :                         trait_aliases[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
     813           0 :                         memcpy(trait_aliases[i]->trait_method, ce->trait_aliases[i]->trait_method, sizeof(zend_trait_method_reference));
     814           0 :                         if (trait_aliases[i]->trait_method) {
     815           0 :                                 if (trait_aliases[i]->trait_method->method_name) {
     816           0 :                                         trait_aliases[i]->trait_method->method_name =
     817           0 :                                                 estrndup(trait_aliases[i]->trait_method->method_name,
     818             :                                                         trait_aliases[i]->trait_method->mname_len);
     819             :                                 }
     820           0 :                                 if (trait_aliases[i]->trait_method->class_name) {
     821           0 :                                         trait_aliases[i]->trait_method->class_name =
     822           0 :                                                 estrndup(trait_aliases[i]->trait_method->class_name,
     823             :                                                         trait_aliases[i]->trait_method->cname_len);
     824             :                                 }
     825             :                         }
     826             : 
     827           0 :                         if (trait_aliases[i]->alias) {
     828           0 :                                 trait_aliases[i]->alias =
     829           0 :                                         estrndup(trait_aliases[i]->alias,
     830             :                                                 trait_aliases[i]->alias_len);
     831             :                         }
     832           0 :                         i++;
     833             :                 }
     834           0 :                 trait_aliases[i] = NULL;
     835           0 :                 ce->trait_aliases = trait_aliases;
     836             :         }
     837             : 
     838           1 :         if (ce->trait_precedences) {
     839             :                 zend_trait_precedence **trait_precedences;
     840           0 :                 int i = 0;
     841             : 
     842           0 :                 while (ce->trait_precedences[i]) {
     843           0 :                         i++;
     844             :                 }
     845           0 :                 trait_precedences = emalloc(sizeof(zend_trait_precedence*) * (i + 1));
     846           0 :                 i = 0;
     847           0 :                 while (ce->trait_precedences[i]) {
     848           0 :                         trait_precedences[i] = emalloc(sizeof(zend_trait_precedence));
     849           0 :                         memcpy(trait_precedences[i], ce->trait_precedences[i], sizeof(zend_trait_precedence));
     850           0 :                         trait_precedences[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
     851           0 :                         memcpy(trait_precedences[i]->trait_method, ce->trait_precedences[i]->trait_method, sizeof(zend_trait_method_reference));
     852             : 
     853           0 :                         trait_precedences[i]->trait_method->method_name =
     854           0 :                                 estrndup(trait_precedences[i]->trait_method->method_name,
     855             :                                         trait_precedences[i]->trait_method->mname_len);
     856           0 :                         trait_precedences[i]->trait_method->class_name =
     857           0 :                                 estrndup(trait_precedences[i]->trait_method->class_name,
     858             :                                         trait_precedences[i]->trait_method->cname_len);
     859             : 
     860           0 :                         if (trait_precedences[i]->exclude_from_classes) {
     861             :                                 zend_class_entry **exclude_from_classes;
     862           0 :                                 int j = 0;
     863             : 
     864           0 :                                 while (trait_precedences[i]->exclude_from_classes[j]) {
     865           0 :                                         j++;
     866             :                                 }
     867           0 :                                 exclude_from_classes = emalloc(sizeof(zend_class_entry*) * (j + 1));
     868           0 :                                 j = 0;
     869           0 :                                 while (trait_precedences[i]->exclude_from_classes[j]) {
     870           0 :                                         exclude_from_classes[j] = (zend_class_entry*)estrndup(
     871             :                                                 (char*)trait_precedences[i]->exclude_from_classes[j],
     872             :                                                 strlen((char*)trait_precedences[i]->exclude_from_classes[j]));
     873           0 :                                         j++;
     874             :                                 }
     875           0 :                                 exclude_from_classes[j] = NULL;
     876           0 :                                 trait_precedences[i]->exclude_from_classes = exclude_from_classes;
     877             :                         }
     878           0 :                         i++;
     879             :                 }
     880           0 :                 trait_precedences[i] = NULL;
     881           0 :                 ce->trait_precedences = trait_precedences;
     882             :         }
     883             : #endif
     884           1 : }
     885             : 
     886          25 : static int zend_hash_unique_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor, uint size, int ignore_dups, void **fail_data, void **conflict_data)
     887             : {
     888             :         Bucket *p;
     889             :         void *t;
     890             : 
     891          25 :         p = source->pListHead;
     892          75 :         while (p) {
     893          25 :                 if (p->nKeyLength > 0) {
     894          25 :                         if (zend_hash_quick_add(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t) == SUCCESS) {
     895          25 :                                 if (pCopyConstructor) {
     896          25 :                                         pCopyConstructor(t);
     897             :                                 }
     898             :                         } else {
     899           0 :                                 if (p->nKeyLength > 0 && p->arKey[0] == 0) {
     900             :                                         /* Mangled key */
     901             : #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
     902           0 :                                         if (zend_hash_quick_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t) == SUCCESS) {
     903           0 :                                                 if (pCopyConstructor) {
     904           0 :                                                         pCopyConstructor(t);
     905             :                                                 }
     906             :                                         }
     907             : #endif
     908           0 :                                 } else if (!ignore_dups && zend_hash_quick_find(target, p->arKey, p->nKeyLength, p->h, &t) == SUCCESS) {
     909           0 :                                         *fail_data = p->pData;
     910           0 :                                         *conflict_data = t;
     911           0 :                                         return FAILURE;
     912             :                                 }
     913             :                         }
     914             :                 } else {
     915           0 :                         if (!zend_hash_index_exists(target, p->h) && zend_hash_index_update(target, p->h, p->pData, size, &t) == SUCCESS) {
     916           0 :                                 if (pCopyConstructor) {
     917           0 :                                         pCopyConstructor(t);
     918             :                                 }
     919           0 :                         } else if (!ignore_dups && zend_hash_index_find(target,p->h, &t) == SUCCESS) {
     920           0 :                                 *fail_data = p->pData;
     921           0 :                                 *conflict_data = t;
     922           0 :                                 return FAILURE;
     923             :                         }
     924             :                 }
     925          25 :                 p = p->pListNext;
     926             :         }
     927          25 :         target->pInternalPointer = target->pListHead;
     928             : 
     929          25 :         return SUCCESS;
     930             : }
     931             : 
     932          24 : static void zend_accel_function_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor)
     933             : {
     934             :         zend_function *function1, *function2;
     935             :         TSRMLS_FETCH();
     936             : 
     937          24 :         if (zend_hash_unique_copy(target, source, pCopyConstructor, sizeof(zend_function), 0, (void**)&function1, (void**)&function2) != SUCCESS) {
     938           0 :                 CG(in_compilation) = 1;
     939           0 :                 zend_set_compiled_filename(function1->op_array.filename TSRMLS_CC);
     940           0 :                 CG(zend_lineno) = function1->op_array.opcodes[0].lineno;
     941           0 :                 if (function2->type == ZEND_USER_FUNCTION
     942           0 :                         && function2->op_array.last > 0) {
     943           0 :                         zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)",
     944           0 :                                            function1->common.function_name,
     945           0 :                                            function2->op_array.filename,
     946           0 :                                            (int)function2->op_array.opcodes[0].lineno);
     947             :                 } else {
     948           0 :                         zend_error(E_ERROR, "Cannot redeclare %s()", function1->common.function_name);
     949             :                 }
     950             :         }
     951          24 : }
     952             : 
     953           1 : static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor TSRMLS_DC)
     954             : {
     955             :         zend_class_entry **pce1, **pce2;
     956             : 
     957           1 :         if (zend_hash_unique_copy(target, source, pCopyConstructor, sizeof(zend_class_entry*), ZCG(accel_directives).ignore_dups, (void**)&pce1, (void**)&pce2) != SUCCESS) {
     958           0 :                 CG(in_compilation) = 1;
     959             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     960           0 :                 zend_set_compiled_filename((*pce1)->info.user.filename TSRMLS_CC);
     961           0 :                 CG(zend_lineno) = (*pce1)->info.user.line_start;
     962             : #else
     963             :                 zend_set_compiled_filename((*pce1)->filename TSRMLS_CC);
     964             :                 CG(zend_lineno) = (*pce1)->line_start;
     965             : #endif
     966           0 :                 zend_error(E_ERROR, "Cannot redeclare class %s", (*pce1)->name);
     967             :         }
     968           1 : }
     969             : 
     970             : #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
     971             : static void zend_do_delayed_early_binding(zend_op_array *op_array, zend_uint early_binding TSRMLS_DC)
     972             : {
     973             :         zend_uint opline_num = early_binding;
     974             : 
     975             :         if ((int)opline_num != -1) {
     976             :                 zend_bool orig_in_compilation = CG(in_compilation);
     977             :                 char *orig_compiled_filename = zend_set_compiled_filename(op_array->filename TSRMLS_CC);
     978             :                 zend_class_entry **pce;
     979             : 
     980             :                 CG(in_compilation) = 1;
     981             :                 while ((int)opline_num != -1) {
     982             :                         if (zend_lookup_class(Z_STRVAL(op_array->opcodes[opline_num - 1].op2.u.constant), Z_STRLEN(op_array->opcodes[opline_num - 1].op2.u.constant), &pce TSRMLS_CC) == SUCCESS) {
     983             :                                 do_bind_inherited_class(&op_array->opcodes[opline_num], EG(class_table), *pce, 1 TSRMLS_CC);
     984             :                         }
     985             :                         opline_num = op_array->opcodes[opline_num].result.u.opline_num;
     986             :                 }
     987             :                 zend_restore_compiled_filename(orig_compiled_filename TSRMLS_CC);
     988             :                 CG(in_compilation) = orig_in_compilation;
     989             :         }
     990             : }
     991             : #endif
     992             : 
     993         422 : zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory TSRMLS_DC)
     994             : {
     995             :         zend_op_array *op_array;
     996             : 
     997         422 :         op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
     998         422 :         *op_array = persistent_script->main_op_array;
     999             : 
    1000         422 :         if (from_shared_memory) {
    1001             :                 /* Copy all the necessary stuff from shared memory to regular memory, and protect the shared script */
    1002         422 :                 if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
    1003           1 :                         zend_hash_init(&ZCG(bind_hash), 10, NULL, NULL, 0);
    1004           1 :                         zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, (unique_copy_ctor_func_t) zend_class_copy_ctor TSRMLS_CC);
    1005           1 :                         zend_hash_destroy(&ZCG(bind_hash));
    1006             :                 }
    1007             :                 /* we must first to copy all classes and then prepare functions, since functions may try to bind
    1008             :                    classes - which depend on pre-bind class entries existent in the class table */
    1009         422 :                 if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
    1010          24 :                         zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table, (unique_copy_ctor_func_t)zend_prepare_function_for_execution);
    1011             :                 }
    1012             : 
    1013         422 :                 zend_prepare_function_for_execution(op_array);
    1014             : 
    1015             :                 /* Register __COMPILER_HALT_OFFSET__ constant */
    1016         517 :                 if (persistent_script->compiler_halt_offset != 0 &&
    1017          95 :                     persistent_script->full_path) {
    1018             :                         char *name, *cfilename;
    1019          95 :                         char haltoff[] = "__COMPILER_HALT_OFFSET__";
    1020             :                         int len, clen;
    1021             : 
    1022          95 :                         cfilename = persistent_script->full_path;
    1023          95 :                         clen = strlen(cfilename);
    1024          95 :                         zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, cfilename, clen, 0);
    1025          95 :                         if (!zend_hash_exists(EG(zend_constants), name, len + 1)) {
    1026           0 :                                 zend_register_long_constant(name, len + 1, persistent_script->compiler_halt_offset, CONST_CS, 0 TSRMLS_CC);
    1027             :                         }
    1028          95 :                         efree(name);
    1029             :                 }
    1030             : 
    1031             : #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
    1032             :                 if ((int)persistent_script->early_binding != -1) {
    1033             :                         zend_do_delayed_early_binding(op_array, persistent_script->early_binding TSRMLS_CC);
    1034             :                 }
    1035             : #endif
    1036             : 
    1037             :         } else /* if (!from_shared_memory) */ {
    1038           0 :                 if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
    1039           0 :                         zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table, NULL);
    1040             :                 }
    1041           0 :                 if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
    1042           0 :                         zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, NULL TSRMLS_CC);
    1043             :                 }
    1044             :         }
    1045             : 
    1046             : #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
    1047         422 :         if (op_array->early_binding != (zend_uint)-1) {
    1048           0 :                 char *orig_compiled_filename = CG(compiled_filename);
    1049           0 :                 CG(compiled_filename) = persistent_script->full_path;
    1050           0 :                 zend_do_delayed_early_binding(op_array TSRMLS_CC);
    1051           0 :                 CG(compiled_filename) = orig_compiled_filename;
    1052             :         }
    1053             : #endif
    1054             : 
    1055         422 :         if (!from_shared_memory) {
    1056           0 :                 free_persistent_script(persistent_script, 0); /* free only hashes */
    1057             :         }
    1058             : 
    1059         422 :         return op_array;
    1060             : }
    1061             : 
    1062             : /*
    1063             :  * zend_adler32() is based on zlib implementation
    1064             :  * Computes the Adler-32 checksum of a data stream
    1065             :  *
    1066             :  * Copyright (C) 1995-2005 Mark Adler
    1067             :  * For conditions of distribution and use, see copyright notice in zlib.h
    1068             :  *
    1069             :  * Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
    1070             :  *
    1071             :  *  This software is provided 'as-is', without any express or implied
    1072             :  *  warranty.  In no event will the authors be held liable for any damages
    1073             :  *  arising from the use of this software.
    1074             :  *
    1075             :  *  Permission is granted to anyone to use this software for any purpose,
    1076             :  *  including commercial applications, and to alter it and redistribute it
    1077             :  *  freely, subject to the following restrictions:
    1078             :  *
    1079             :  *  1. The origin of this software must not be misrepresented; you must not
    1080             :  *     claim that you wrote the original software. If you use this software
    1081             :  *     in a product, an acknowledgment in the product documentation would be
    1082             :  *     appreciated but is not required.
    1083             :  *  2. Altered source versions must be plainly marked as such, and must not be
    1084             :  *     misrepresented as being the original software.
    1085             :  *  3. This notice may not be removed or altered from any source distribution.
    1086             :  *
    1087             :  */
    1088             : 
    1089             : #define ADLER32_BASE 65521 /* largest prime smaller than 65536 */
    1090             : #define ADLER32_NMAX 5552
    1091             : /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
    1092             : 
    1093             : #define ADLER32_DO1(buf)        {s1 += *(buf); s2 += s1;}
    1094             : #define ADLER32_DO2(buf, i)     ADLER32_DO1(buf + i); ADLER32_DO1(buf + i + 1);
    1095             : #define ADLER32_DO4(buf, i)     ADLER32_DO2(buf, i); ADLER32_DO2(buf, i + 2);
    1096             : #define ADLER32_DO8(buf, i)     ADLER32_DO4(buf, i); ADLER32_DO4(buf, i + 4);
    1097             : #define ADLER32_DO16(buf)       ADLER32_DO8(buf, 0); ADLER32_DO8(buf, 8);
    1098             : 
    1099         844 : unsigned int zend_adler32(unsigned int checksum, signed char *buf, uint len)
    1100             : {
    1101         844 :         unsigned int s1 = checksum & 0xffff;
    1102         844 :         unsigned int s2 = (checksum >> 16) & 0xffff;
    1103             :         signed char *end;
    1104             : 
    1105        1698 :         while (len >= ADLER32_NMAX) {
    1106          10 :                 len -= ADLER32_NMAX;
    1107          10 :                 end = buf + ADLER32_NMAX;
    1108             :                 do {
    1109        3470 :                         ADLER32_DO16(buf);
    1110        3470 :                         buf += 16;
    1111        3470 :                 } while (buf != end);
    1112          10 :                 s1 %= ADLER32_BASE;
    1113          10 :                 s2 %= ADLER32_BASE;
    1114             :         }
    1115             : 
    1116         844 :         if (len) {
    1117         844 :                 if (len >= 16) {
    1118         844 :                         end = buf + (len & 0xfff0);
    1119         844 :                         len &= 0xf;
    1120             :                         do {
    1121       38272 :                                 ADLER32_DO16(buf);
    1122       38272 :                                 buf += 16;
    1123       38272 :                         } while (buf != end);
    1124             :                 }
    1125         844 :                 if (len) {
    1126         234 :                         end = buf + len;
    1127             :                         do {
    1128        1872 :                                 ADLER32_DO1(buf);
    1129        1872 :                                 buf++;
    1130        1872 :                         } while (buf != end);
    1131             :                 }
    1132         844 :                 s1 %= ADLER32_BASE;
    1133         844 :                 s2 %= ADLER32_BASE;
    1134             :         }
    1135             : 
    1136         844 :         return (s2 << 16) | s1;
    1137             : }

Generated by: LCOV version 1.10

Generated at Mon, 04 Aug 2014 15:49:08 +0000 (17 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.