root/ext/opcache/zend_accelerator_util_funcs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zend_accel_destroy_zend_function
  2. zend_accel_destroy_zend_class
  3. create_persistent_script
  4. compact_hash_table
  5. compact_persistent_script
  6. free_persistent_script
  7. is_not_internal_function
  8. zend_accel_free_user_functions
  9. move_user_function
  10. zend_accel_move_user_functions
  11. copy_internal_function
  12. zend_accel_copy_internal_functions
  13. zend_destroy_property_info
  14. zend_ast_clone
  15. zend_clone_zval
  16. zend_hash_clone_zval
  17. zend_hash_clone_methods
  18. zend_hash_clone_prop_info
  19. zend_prepare_function_for_execution
  20. zend_class_copy_ctor
  21. zend_hash_unique_copy
  22. zend_accel_function_hash_copy
  23. zend_accel_class_hash_copy
  24. zend_do_delayed_early_binding
  25. zend_accel_load_script
  26. zend_adler32

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

/* [<][>][^][v][top][bottom][index][help] */