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: 285 444 64.2 %
Date: 2015-06-27 Functions: 19 21 90.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend OPcache                                                         |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2015 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             : #if SIZEOF_SIZE_T <= SIZEOF_ZEND_LONG
      29             : /* If sizeof(void*) == sizeof(ulong) we can use zend_hash index functions */
      30             : # define accel_xlat_set(old, new)       zend_hash_index_add_new_ptr(&ZCG(bind_hash), (zend_ulong)(zend_uintptr_t)(old), (new))
      31             : # define accel_xlat_get(old)            zend_hash_index_find_ptr(&ZCG(bind_hash), (zend_ulong)(zend_uintptr_t)(old))
      32             : #else
      33             : # define accel_xlat_set(old, new)       (zend_hash_str_add_new_ptr(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (zend_ulong)(zend_uintptr_t)(old), (void**)&(new))
      34             : # define accel_xlat_get(old, new)       ((new) = zend_hash_str_find_ptr(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (zend_ulong)(zend_uintptr_t)(old), (void**)&(new)))
      35             : #endif
      36             : 
      37             : #define ARENA_REALLOC(ptr) \
      38             :         (void*)(((char*)(ptr)) + ((char*)ZCG(arena_mem) - (char*)ZCG(current_persistent_script)->arena_mem))
      39             : 
      40             : typedef int (*id_function_t)(void *, void *);
      41             : typedef void (*unique_copy_ctor_func_t)(void *pElement);
      42             : 
      43             : static zend_ast *zend_ast_clone(zend_ast *ast);
      44             : 
      45           4 : static void zend_accel_destroy_zend_function(zval *zv)
      46             : {
      47           4 :         zend_function *function = Z_PTR_P(zv);
      48             : 
      49           4 :         if (function->type == ZEND_USER_FUNCTION) {
      50           4 :                 if (function->op_array.static_variables) {
      51           0 :                         if (!(GC_FLAGS(function->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
      52           0 :                                 if (--GC_REFCOUNT(function->op_array.static_variables) == 0) {
      53           0 :                                         FREE_HASHTABLE(function->op_array.static_variables);
      54             :                                 }
      55             :                         }
      56           0 :                         function->op_array.static_variables = NULL;
      57             :                 }
      58             :         }
      59             : 
      60           4 :         destroy_zend_function(function);
      61           4 : }
      62             : 
      63           4 : static void zend_accel_destroy_zend_class(zval *zv)
      64             : {
      65           4 :         zend_class_entry *ce = Z_PTR_P(zv);
      66           4 :         ce->function_table.pDestructor = zend_accel_destroy_zend_function;
      67           4 :         destroy_zend_class(zv);
      68           4 : }
      69             : 
      70         430 : zend_persistent_script* create_persistent_script(void)
      71             : {
      72         430 :         zend_persistent_script *persistent_script = (zend_persistent_script *) emalloc(sizeof(zend_persistent_script));
      73         430 :         memset(persistent_script, 0, sizeof(zend_persistent_script));
      74             : 
      75         430 :         zend_hash_init(&persistent_script->function_table, 128, NULL, ZEND_FUNCTION_DTOR, 0);
      76             :         /* class_table is usually destroyed by free_persistent_script() that
      77             :          * overrides destructor. ZEND_CLASS_DTOR may be used by standard
      78             :          * PHP compiler
      79             :          */
      80         430 :         zend_hash_init(&persistent_script->class_table, 16, NULL, ZEND_CLASS_DTOR, 0);
      81             : 
      82         430 :         return persistent_script;
      83             : }
      84             : 
      85           3 : void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements)
      86             : {
      87           3 :         if (destroy_elements) {
      88           3 :                 persistent_script->function_table.pDestructor = zend_accel_destroy_zend_function;
      89           3 :                 persistent_script->class_table.pDestructor = zend_accel_destroy_zend_class;
      90             :         } else {
      91           0 :                 persistent_script->function_table.pDestructor = NULL;
      92           0 :                 persistent_script->class_table.pDestructor = NULL;
      93             :         }
      94             : 
      95           3 :         zend_hash_destroy(&persistent_script->function_table);
      96           3 :         zend_hash_destroy(&persistent_script->class_table);
      97             : 
      98           3 :         if (persistent_script->full_path) {
      99           0 :                 zend_string_release(persistent_script->full_path);
     100             :         }
     101             : 
     102           3 :         efree(persistent_script);
     103           3 : }
     104             : 
     105        6217 : static int is_not_internal_function(zval *zv)
     106             : {
     107        6217 :         zend_function *function = Z_PTR_P(zv);
     108        6217 :         return(function->type != ZEND_INTERNAL_FUNCTION);
     109             : }
     110             : 
     111           3 : void zend_accel_free_user_functions(HashTable *ht)
     112             : {
     113           3 :         dtor_func_t orig_dtor = ht->pDestructor;
     114             : 
     115           3 :         ht->pDestructor = NULL;
     116           3 :         zend_hash_apply(ht, (apply_func_t) is_not_internal_function);
     117           3 :         ht->pDestructor = orig_dtor;
     118           3 : }
     119             : 
     120         427 : void zend_accel_move_user_functions(HashTable *src, HashTable *dst)
     121             : {
     122             :         Bucket *p;
     123         427 :         dtor_func_t orig_dtor = src->pDestructor;
     124             : 
     125         427 :         src->pDestructor = NULL;
     126         427 :         zend_hash_extend(dst, dst->nNumUsed + src->nNumUsed, 0);
     127         948 :         ZEND_HASH_REVERSE_FOREACH_BUCKET(src, p) {
     128         451 :                 zend_function *function = Z_PTR(p->val);
     129             : 
     130         451 :                 if (EXPECTED(function->type == ZEND_USER_FUNCTION)) {
     131          24 :                         _zend_hash_append_ptr(dst, p->key, function);
     132          24 :                         zend_hash_del_bucket(src, p);
     133             :                 } else {
     134         427 :                         break;
     135             :                 }
     136             :         } ZEND_HASH_FOREACH_END();
     137         427 :         src->pDestructor = orig_dtor;
     138         427 : }
     139             : 
     140      775449 : static int copy_internal_function(zval *zv, HashTable *function_table)
     141             : {
     142      775449 :         zend_internal_function *function = Z_PTR_P(zv);
     143      775449 :         if (function->type == ZEND_INTERNAL_FUNCTION) {
     144      775449 :                 zend_hash_update_mem(function_table, function->function_name, function, sizeof(zend_internal_function));
     145             :         }
     146      775449 :         return 0;
     147             : }
     148             : 
     149         374 : void zend_accel_copy_internal_functions(void)
     150             : {
     151         374 :         zend_hash_apply_with_argument(CG(function_table), (apply_func_arg_t)copy_internal_function, &ZCG(function_table));
     152         374 :         ZCG(internal_functions_count) = zend_hash_num_elements(&ZCG(function_table));
     153         374 : }
     154             : 
     155           7 : static inline void zend_clone_zval(zval *src)
     156             : {
     157             :         void *ptr;
     158             : 
     159           7 :         if (Z_TYPE_P(src) == IS_REFERENCE) {
     160           0 :                 ptr = accel_xlat_get(Z_REF_P(src));
     161           0 :                 if (ptr != NULL) {
     162           0 :                         Z_REF_P(src) = ptr;
     163           0 :                         return;
     164             :                 } else {
     165           0 :                         zend_reference *old = Z_REF_P(src);
     166           0 :                         ZVAL_NEW_REF(src, &old->val);
     167           0 :                         Z_REF_P(src)->gc = old->gc;
     168           0 :                         accel_xlat_set(old, Z_REF_P(src));
     169           0 :                         src = Z_REFVAL_P(src);
     170             :                 }
     171             :         }
     172           7 :         if (Z_TYPE_P(src) == IS_CONSTANT_AST) {
     173           0 :                 if (Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_AST_P(src))) != NULL) {
     174           0 :                         Z_AST_P(src) = ptr;
     175             :                 } else {
     176           0 :                         zend_ast_ref *old = Z_AST_P(src);
     177             : 
     178           0 :                         ZVAL_NEW_AST(src, old->ast);
     179           0 :                         Z_AST_P(src)->gc = old->gc;
     180           0 :                         if (Z_REFCOUNT_P(src) > 1) {
     181           0 :                                 accel_xlat_set(old, Z_AST_P(src));
     182             :                         }
     183           0 :                         Z_ASTVAL_P(src) = zend_ast_clone(Z_ASTVAL_P(src));
     184             :                 }
     185             :         }
     186             : }
     187             : 
     188           0 : static zend_ast *zend_ast_clone(zend_ast *ast)
     189             : {
     190             :         uint32_t i;
     191             : 
     192           0 :         if (ast->kind == ZEND_AST_ZVAL) {
     193           0 :                 zend_ast_zval *copy = emalloc(sizeof(zend_ast_zval));
     194           0 :                 copy->kind = ZEND_AST_ZVAL;
     195           0 :                 copy->attr = ast->attr;
     196           0 :                 ZVAL_COPY_VALUE(&copy->val, zend_ast_get_zval(ast));
     197           0 :                 return (zend_ast *) copy;
     198           0 :         } else if (zend_ast_is_list(ast)) {
     199           0 :                 zend_ast_list *list = zend_ast_get_list(ast);
     200           0 :                 zend_ast_list *copy = emalloc(
     201             :                         sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
     202           0 :                 copy->kind = list->kind;
     203           0 :                 copy->attr = list->attr;
     204           0 :                 copy->children = list->children;
     205           0 :                 for (i = 0; i < list->children; i++) {
     206           0 :                         if (list->child[i]) {
     207           0 :                                 copy->child[i] = zend_ast_clone(list->child[i]);
     208             :                         } else {
     209           0 :                                 copy->child[i] = NULL;
     210             :                         }
     211             :                 }
     212           0 :                 return (zend_ast *) copy;
     213             :         } else {
     214           0 :                 uint32_t children = zend_ast_get_num_children(ast);
     215           0 :                 zend_ast *copy = emalloc(sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children);
     216           0 :                 copy->kind = ast->kind;
     217           0 :                 copy->attr = ast->attr;
     218           0 :                 for (i = 0; i < children; i++) {
     219           0 :                         if (ast->child[i]) {
     220           0 :                                 copy->child[i] = zend_ast_clone(ast->child[i]);
     221             :                         } else {
     222           0 :                                 copy->child[i] = NULL;
     223             :                         }
     224             :                 }
     225           0 :                 return copy;
     226             :         }
     227             : }
     228             : 
     229           7 : static void zend_hash_clone_constants(HashTable *ht, HashTable *source)
     230             : {
     231             :         Bucket *p, *q, *end;
     232             :         zend_ulong nIndex;
     233             : 
     234           7 :         ht->nTableSize = source->nTableSize;
     235           7 :         ht->nTableMask = source->nTableMask;
     236           7 :         ht->nNumUsed = 0;
     237           7 :         ht->nNumOfElements = source->nNumOfElements;
     238           7 :         ht->nNextFreeElement = source->nNextFreeElement;
     239           7 :         ht->pDestructor = ZVAL_PTR_DTOR;
     240           7 :         ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED) | HASH_FLAG_APPLY_PROTECTION;
     241           7 :         ht->nInternalPointer = source->nNumOfElements ? 0 : HT_INVALID_IDX;
     242             : 
     243           7 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
     244           6 :                 ht->arData = source->arData;
     245           6 :                 return;
     246             :         }
     247             : 
     248             :         ZEND_ASSERT((source->u.flags & HASH_FLAG_PACKED) == 0);
     249           1 :         HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht)));
     250           1 :         HT_HASH_RESET(ht);
     251             : 
     252           1 :         p = source->arData;
     253           1 :         end = p + source->nNumUsed;
     254           6 :         for (; p != end; p++) {
     255          10 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
     256           5 :                 nIndex = p->h | ht->nTableMask;
     257             : 
     258             :                 /* Insert into hash collision list */
     259           5 :                 q = ht->arData + ht->nNumUsed;
     260           5 :                 Z_NEXT(q->val) = HT_HASH(ht, nIndex);
     261           5 :                 HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(ht->nNumUsed++);
     262             : 
     263             :                 /* Initialize key */
     264           5 :                 q->h = p->h;
     265           5 :                 q->key = p->key;
     266             : 
     267             :                 /* Copy data */
     268           5 :                 ZVAL_COPY_VALUE(&q->val, &p->val);
     269           5 :                 zend_clone_zval(&q->val);
     270             :         }
     271             : }
     272             : 
     273           7 : static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce)
     274             : {
     275             :         Bucket *p, *q, *end;
     276             :         zend_ulong nIndex;
     277             :         zend_op_array *new_entry;
     278             : 
     279           7 :         ht->nTableSize = source->nTableSize;
     280           7 :         ht->nTableMask = source->nTableMask;
     281           7 :         ht->nNumUsed = 0;
     282           7 :         ht->nNumOfElements = source->nNumOfElements;
     283           7 :         ht->nNextFreeElement = source->nNextFreeElement;
     284           7 :         ht->pDestructor = ZEND_FUNCTION_DTOR;
     285           7 :         ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED);
     286           7 :         ht->nInternalPointer = source->nNumOfElements ? 0 : HT_INVALID_IDX;
     287             : 
     288           7 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
     289           2 :                 ht->arData = source->arData;
     290           2 :                 return;
     291             :         }
     292             : 
     293             :         ZEND_ASSERT(!(source->u.flags & HASH_FLAG_PACKED));
     294           5 :         HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht)));
     295           5 :         HT_HASH_RESET(ht);
     296             : 
     297           5 :         p = source->arData;
     298           5 :         end = p + source->nNumUsed;
     299          14 :         for (; p != end; p++) {
     300          18 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
     301             : 
     302           9 :                 nIndex = p->h | ht->nTableMask;
     303             : 
     304             :                 /* Insert into hash collision list */
     305           9 :                 q = ht->arData + ht->nNumUsed;
     306           9 :                 Z_NEXT(q->val) = HT_HASH(ht, nIndex);
     307           9 :                 HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(ht->nNumUsed++);
     308             : 
     309             :                 /* Initialize key */
     310           9 :                 q->h = p->h;
     311             :                 ZEND_ASSERT(p->key != NULL);
     312           9 :                 q->key = p->key;
     313             : 
     314             :                 /* Copy data */
     315           9 :                 ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val)));
     316           9 :                 new_entry = (zend_op_array*)Z_PTR(q->val);
     317             : 
     318          18 :                 if ((void*)new_entry->scope >= ZCG(current_persistent_script)->arena_mem &&
     319           9 :                     (void*)new_entry->scope < (void*)((char*)ZCG(current_persistent_script)->arena_mem + ZCG(current_persistent_script)->arena_size)) {
     320             : 
     321           9 :                         new_entry->scope = ARENA_REALLOC(new_entry->scope);
     322             : 
     323             :                         /* update prototype */
     324           9 :                         if (new_entry->prototype) {
     325           2 :                                 new_entry->prototype = ARENA_REALLOC(new_entry->prototype);
     326             :                         }
     327             :                 }
     328             :         }
     329             : }
     330             : 
     331           7 : static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_class_entry *old_ce)
     332             : {
     333             :         Bucket *p, *q, *end;
     334             :         zend_ulong nIndex;
     335             :         zend_property_info *prop_info;
     336             : 
     337           7 :         ht->nTableSize = source->nTableSize;
     338           7 :         ht->nTableMask = source->nTableMask;
     339           7 :         ht->nNumUsed = 0;
     340           7 :         ht->nNumOfElements = source->nNumOfElements;
     341           7 :         ht->nNextFreeElement = source->nNextFreeElement;
     342           7 :         ht->pDestructor = NULL;
     343           7 :         ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED);
     344           7 :         ht->nInternalPointer = source->nNumOfElements ? 0 : HT_INVALID_IDX;
     345             : 
     346           7 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
     347           6 :                 ht->arData = source->arData;
     348           6 :                 return;
     349             :         }
     350             : 
     351             :         ZEND_ASSERT(!(source->u.flags & HASH_FLAG_PACKED));
     352           1 :         HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht)));
     353           1 :         HT_HASH_RESET(ht);
     354             : 
     355           1 :         p = source->arData;
     356           1 :         end = p + source->nNumUsed;
     357           3 :         for (; p != end; p++) {
     358           4 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
     359             : 
     360           2 :                 nIndex = p->h | ht->nTableMask;
     361             : 
     362             :                 /* Insert into hash collision list */
     363           2 :                 q = ht->arData + ht->nNumUsed;
     364           2 :                 Z_NEXT(q->val) = HT_HASH(ht, nIndex);
     365           2 :                 HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(ht->nNumUsed++);
     366             : 
     367             :                 /* Initialize key */
     368           2 :                 q->h = p->h;
     369             :                 ZEND_ASSERT(p->key != NULL);
     370           2 :                 q->key = p->key;
     371             : 
     372             :                 /* Copy data */
     373           2 :                 prop_info = ARENA_REALLOC(Z_PTR(p->val));
     374           2 :                 ZVAL_PTR(&q->val, prop_info);
     375             : 
     376           4 :                 if ((void*)prop_info->ce >= ZCG(current_persistent_script)->arena_mem &&
     377           2 :                     (void*)prop_info->ce < (void*)((char*)ZCG(current_persistent_script)->arena_mem + ZCG(current_persistent_script)->arena_size)) {
     378           2 :                         prop_info->ce = ARENA_REALLOC(prop_info->ce);
     379             :                 }
     380             :         }
     381             : }
     382             : 
     383             : #define zend_update_inherited_handler(handler) \
     384             : { \
     385             :         if (ce->handler != NULL) { \
     386             :                 ce->handler = ARENA_REALLOC(ce->handler); \
     387             :         } \
     388             : }
     389             : 
     390             : /* Protects class' refcount, copies default properties, functions and class name */
     391           7 : static void zend_class_copy_ctor(zend_class_entry **pce)
     392             : {
     393           7 :         zend_class_entry *ce = *pce;
     394           7 :         zend_class_entry *old_ce = ce;
     395             :         zval *src, *dst, *end;
     396             : 
     397           7 :         *pce = ce = ARENA_REALLOC(old_ce);
     398           7 :         ce->refcount = 1;
     399             : 
     400           7 :         if (old_ce->default_properties_table) {
     401           0 :                 ce->default_properties_table = emalloc(sizeof(zval) * old_ce->default_properties_count);
     402           0 :                 src = old_ce->default_properties_table;
     403           0 :                 end = src + old_ce->default_properties_count;
     404           0 :                 dst = ce->default_properties_table;
     405           0 :                 for (; src != end; src++, dst++) {
     406           0 :                         ZVAL_COPY_VALUE(dst, src);
     407           0 :                         zend_clone_zval(dst);
     408             :                 }
     409             :         }
     410             : 
     411           7 :         zend_hash_clone_methods(&ce->function_table, &old_ce->function_table, old_ce, ce);
     412             : 
     413             :         /* static members */
     414           7 :         if (old_ce->default_static_members_table) {
     415           1 :                 ce->default_static_members_table = emalloc(sizeof(zval) * old_ce->default_static_members_count);
     416           1 :                 src = old_ce->default_static_members_table;
     417           1 :                 end = src + old_ce->default_static_members_count;
     418           1 :                 dst = ce->default_static_members_table;
     419           3 :                 for (; src != end; src++, dst++) {
     420           2 :                         ZVAL_COPY_VALUE(dst, src);
     421           2 :                         zend_clone_zval(dst);
     422             :                 }
     423             :         }
     424           7 :         ce->static_members_table = ce->default_static_members_table;
     425             : 
     426             :         /* properties_info */
     427           7 :         zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce);
     428             : 
     429             :         /* constants table */
     430           7 :         zend_hash_clone_constants(&ce->constants_table, &old_ce->constants_table);
     431           7 :         ce->constants_table.u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     432             : 
     433             :         /* interfaces aren't really implemented, so we create a new table */
     434           7 :         if (ce->num_interfaces) {
     435           0 :                 ce->interfaces = emalloc(sizeof(zend_class_entry *) * ce->num_interfaces);
     436           0 :                 memset(ce->interfaces, 0, sizeof(zend_class_entry *) * ce->num_interfaces);
     437             :         } else {
     438           7 :                 ce->interfaces = NULL;
     439             :         }
     440             : 
     441           7 :         if (ce->parent) {
     442           3 :                 ce->parent = ARENA_REALLOC(ce->parent);
     443             :         }
     444             : 
     445           7 :         zend_update_inherited_handler(constructor);
     446           7 :         zend_update_inherited_handler(destructor);
     447           7 :         zend_update_inherited_handler(clone);
     448           7 :         zend_update_inherited_handler(__get);
     449           7 :         zend_update_inherited_handler(__set);
     450           7 :         zend_update_inherited_handler(__call);
     451             : /* 5.1 stuff */
     452           7 :         zend_update_inherited_handler(serialize_func);
     453           7 :         zend_update_inherited_handler(unserialize_func);
     454           7 :         zend_update_inherited_handler(__isset);
     455           7 :         zend_update_inherited_handler(__unset);
     456             : /* 5.2 stuff */
     457           7 :         zend_update_inherited_handler(__tostring);
     458             : 
     459             : /* 5.3 stuff */
     460           7 :         zend_update_inherited_handler(__callstatic);
     461           7 :         zend_update_inherited_handler(__debugInfo);
     462             : 
     463             : /* 5.4 traits */
     464           7 :         if (ce->trait_aliases) {
     465             :                 zend_trait_alias **trait_aliases;
     466           0 :                 int i = 0;
     467             : 
     468           0 :                 while (ce->trait_aliases[i]) {
     469           0 :                         i++;
     470             :                 }
     471           0 :                 trait_aliases = emalloc(sizeof(zend_trait_alias*) * (i + 1));
     472           0 :                 i = 0;
     473           0 :                 while (ce->trait_aliases[i]) {
     474           0 :                         trait_aliases[i] = emalloc(sizeof(zend_trait_alias));
     475           0 :                         memcpy(trait_aliases[i], ce->trait_aliases[i], sizeof(zend_trait_alias));
     476           0 :                         trait_aliases[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
     477           0 :                         memcpy(trait_aliases[i]->trait_method, ce->trait_aliases[i]->trait_method, sizeof(zend_trait_method_reference));
     478           0 :                         i++;
     479             :                 }
     480           0 :                 trait_aliases[i] = NULL;
     481           0 :                 ce->trait_aliases = trait_aliases;
     482             :         }
     483             : 
     484           7 :         if (ce->trait_precedences) {
     485             :                 zend_trait_precedence **trait_precedences;
     486           0 :                 int i = 0;
     487             : 
     488           0 :                 while (ce->trait_precedences[i]) {
     489           0 :                         i++;
     490             :                 }
     491           0 :                 trait_precedences = emalloc(sizeof(zend_trait_precedence*) * (i + 1));
     492           0 :                 i = 0;
     493           0 :                 while (ce->trait_precedences[i]) {
     494           0 :                         trait_precedences[i] = emalloc(sizeof(zend_trait_precedence));
     495           0 :                         memcpy(trait_precedences[i], ce->trait_precedences[i], sizeof(zend_trait_precedence));
     496           0 :                         trait_precedences[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
     497           0 :                         memcpy(trait_precedences[i]->trait_method, ce->trait_precedences[i]->trait_method, sizeof(zend_trait_method_reference));
     498             : 
     499           0 :                         if (trait_precedences[i]->exclude_from_classes) {
     500             :                                 zend_string **exclude_from_classes;
     501           0 :                                 int j = 0;
     502             : 
     503           0 :                                 while (trait_precedences[i]->exclude_from_classes[j].class_name) {
     504           0 :                                         j++;
     505             :                                 }
     506           0 :                                 exclude_from_classes = emalloc(sizeof(zend_string*) * (j + 1));
     507           0 :                                 j = 0;
     508           0 :                                 while (trait_precedences[i]->exclude_from_classes[j].class_name) {
     509           0 :                                         exclude_from_classes[j] =
     510           0 :                                                 trait_precedences[i]->exclude_from_classes[j].class_name;
     511           0 :                                         j++;
     512             :                                 }
     513           0 :                                 exclude_from_classes[j] = NULL;
     514           0 :                                 trait_precedences[i]->exclude_from_classes = (void*)exclude_from_classes;
     515             :                         }
     516           0 :                         i++;
     517             :                 }
     518           0 :                 trait_precedences[i] = NULL;
     519           0 :                 ce->trait_precedences = trait_precedences;
     520             :         }
     521           7 : }
     522             : 
     523           0 : static void zend_accel_function_hash_copy(HashTable *target, HashTable *source)
     524             : {
     525             :         zend_function *function1, *function2;
     526             :         Bucket *p, *end;
     527             :         zval *t;
     528             : 
     529           0 :         zend_hash_extend(target, target->nNumUsed + source->nNumUsed, 0);
     530           0 :         p = source->arData;
     531           0 :         end = p + source->nNumUsed;
     532           0 :         for (; p != end; p++) {
     533           0 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
     534             :                 ZEND_ASSERT(p->key);
     535           0 :                 t = zend_hash_find(target, p->key);
     536           0 :                 if (UNEXPECTED(t != NULL)) {
     537           0 :                         if (EXPECTED(p->key->len > 0) && EXPECTED(p->key->val[0] == 0)) {
     538             :                                 /* Mangled key */
     539           0 :                                 t = zend_hash_update(target, p->key, &p->val);
     540             :                         } else {
     541             :                                 goto failure;
     542             :                         }
     543             :                 } else {
     544           0 :                         _zend_hash_append_ptr(target, p->key, Z_PTR(p->val));
     545             :                 }
     546             :         }
     547           0 :         target->nInternalPointer = target->nNumOfElements ? 0 : HT_INVALID_IDX;
     548           0 :         return;
     549             : 
     550             : failure:
     551           0 :         function1 = Z_PTR(p->val);
     552           0 :         function2 = Z_PTR_P(t);
     553           0 :         CG(in_compilation) = 1;
     554           0 :         zend_set_compiled_filename(function1->op_array.filename);
     555           0 :         CG(zend_lineno) = function1->op_array.opcodes[0].lineno;
     556           0 :         if (function2->type == ZEND_USER_FUNCTION
     557           0 :                 && function2->op_array.last > 0) {
     558           0 :                 zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)",
     559           0 :                                    function1->common.function_name->val,
     560           0 :                                    function2->op_array.filename->val,
     561           0 :                                    (int)function2->op_array.opcodes[0].lineno);
     562             :         } else {
     563           0 :                 zend_error(E_ERROR, "Cannot redeclare %s()", function1->common.function_name->val);
     564             :         }
     565             : }
     566             : 
     567          24 : static void zend_accel_function_hash_copy_from_shm(HashTable *target, HashTable *source)
     568             : {
     569             :         zend_function *function1, *function2;
     570             :         Bucket *p, *end;
     571             :         zval *t;
     572             : 
     573          24 :         zend_hash_extend(target, target->nNumUsed + source->nNumUsed, 0);
     574          24 :         p = source->arData;
     575          24 :         end = p + source->nNumUsed;
     576          48 :         for (; p != end; p++) {
     577          48 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
     578             :                 ZEND_ASSERT(p->key);
     579          24 :                 t = zend_hash_find(target, p->key);
     580          24 :                 if (UNEXPECTED(t != NULL)) {
     581           0 :                         if (EXPECTED(p->key->len > 0) && EXPECTED(p->key->val[0] == 0)) {
     582             :                                 /* Mangled key */
     583           0 :                                 zend_hash_update_ptr(target, p->key, ARENA_REALLOC(Z_PTR(p->val)));
     584             :                         } else {
     585             :                                 goto failure;
     586             :                         }
     587             :                 } else {
     588          24 :                         _zend_hash_append_ptr(target, p->key, ARENA_REALLOC(Z_PTR(p->val)));
     589             :                 }
     590             :         }
     591          24 :         target->nInternalPointer = target->nNumOfElements ? 0 : HT_INVALID_IDX;
     592          24 :         return;
     593             : 
     594             : failure:
     595           0 :         function1 = Z_PTR(p->val);
     596           0 :         function2 = Z_PTR_P(t);
     597           0 :         CG(in_compilation) = 1;
     598           0 :         zend_set_compiled_filename(function1->op_array.filename);
     599           0 :         CG(zend_lineno) = function1->op_array.opcodes[0].lineno;
     600           0 :         if (function2->type == ZEND_USER_FUNCTION
     601           0 :                 && function2->op_array.last > 0) {
     602           0 :                 zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)",
     603           0 :                                    function1->common.function_name->val,
     604           0 :                                    function2->op_array.filename->val,
     605           0 :                                    (int)function2->op_array.opcodes[0].lineno);
     606             :         } else {
     607           0 :                 zend_error(E_ERROR, "Cannot redeclare %s()", function1->common.function_name->val);
     608             :         }
     609             : }
     610             : 
     611           4 : static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor)
     612             : {
     613             :         zend_class_entry *ce1;
     614             :         Bucket *p, *end;
     615             :         zval *t;
     616             : 
     617           4 :         zend_hash_extend(target, target->nNumUsed + source->nNumUsed, 0);
     618           4 :         p = source->arData;
     619           4 :         end = p + source->nNumUsed;
     620          18 :         for (; p != end; p++) {
     621          28 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
     622             :                 ZEND_ASSERT(p->key);
     623           7 :                 t = zend_hash_find(target, p->key);
     624           7 :                 if (UNEXPECTED(t != NULL)) {
     625           0 :                         if (EXPECTED(p->key->len > 0) && EXPECTED(p->key->val[0] == 0)) {
     626             :                                 /* Mangled key - ignore and wait for runtime */
     627           0 :                                 continue;
     628           0 :                         } else if (UNEXPECTED(!ZCG(accel_directives).ignore_dups)) {
     629           0 :                                 goto failure;
     630             :                         }
     631             :                 } else {
     632          14 :                         t = _zend_hash_append_ptr(target, p->key, Z_PTR(p->val));
     633           7 :                         if (pCopyConstructor) {
     634           7 :                                 pCopyConstructor(&Z_PTR_P(t));
     635             :                         }
     636             :                 }
     637             :         }
     638           4 :         target->nInternalPointer = target->nNumOfElements ? 0 : HT_INVALID_IDX;
     639           4 :         return;
     640             : 
     641             : failure:
     642           0 :         ce1 = Z_PTR(p->val);
     643           0 :         CG(in_compilation) = 1;
     644           0 :         zend_set_compiled_filename(ce1->info.user.filename);
     645           0 :         CG(zend_lineno) = ce1->info.user.line_start;
     646           0 :         zend_error(E_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce1), ce1->name->val);
     647             : }
     648             : 
     649             : #ifdef __SSE2__
     650             : #include <mmintrin.h>
     651             : #include <emmintrin.h>
     652             : 
     653             : static zend_always_inline void fast_memcpy(void *dest, const void *src, size_t size)
     654             : {
     655          28 :         __m128i *dqdest = (__m128i*)dest;
     656          28 :         const __m128i *dqsrc  = (const __m128i*)src;
     657          28 :         const __m128i *end  = (const __m128i*)((const char*)src + size);
     658             : 
     659             :         do {
     660         184 :                 _mm_prefetch(dqsrc + 4, _MM_HINT_NTA);
     661             : 
     662         184 :                 __m128i xmm0 = _mm_load_si128(dqsrc + 0);
     663         368 :                 __m128i xmm1 = _mm_load_si128(dqsrc + 1);
     664         368 :                 __m128i xmm2 = _mm_load_si128(dqsrc + 2);
     665         368 :                 __m128i xmm3 = _mm_load_si128(dqsrc + 3);
     666         184 :                 dqsrc  += 4;
     667             :                 _mm_stream_si128(dqdest + 0, xmm0);
     668         184 :                 _mm_stream_si128(dqdest + 1, xmm1);
     669         184 :                 _mm_stream_si128(dqdest + 2, xmm2);
     670         184 :                 _mm_stream_si128(dqdest + 3, xmm3);
     671         184 :                 dqdest += 4;
     672         184 :         } while (dqsrc != end);
     673             : }
     674             : #endif
     675             : 
     676         427 : zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory)
     677             : {
     678             :         zend_op_array *op_array;
     679             : 
     680         427 :         op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
     681         427 :         *op_array = persistent_script->main_op_array;
     682             : 
     683         427 :         if (EXPECTED(from_shared_memory)) {
     684         427 :                 zend_hash_init(&ZCG(bind_hash), 10, NULL, NULL, 0);
     685             : 
     686         427 :                 ZCG(current_persistent_script) = persistent_script;
     687         427 :                 ZCG(arena_mem) = NULL;
     688         427 :                 if (EXPECTED(persistent_script->arena_size)) {
     689             : #ifdef __SSE2__
     690             :                         /* Target address must be aligned to 64-byte boundary */
     691          56 :                         ZCG(arena_mem) = zend_arena_alloc(&CG(arena), persistent_script->arena_size + 64);
     692          28 :                         ZCG(arena_mem) = (void*)(((zend_uintptr_t)ZCG(arena_mem) + 63L) & ~63L);
     693          28 :                         fast_memcpy(ZCG(arena_mem), persistent_script->arena_mem, persistent_script->arena_size);
     694             : #else
     695             :                         ZCG(arena_mem) = zend_arena_alloc(&CG(arena), persistent_script->arena_size);
     696             :                         memcpy(ZCG(arena_mem), persistent_script->arena_mem, persistent_script->arena_size);
     697             : #endif
     698             :                 }
     699             : 
     700             :                 /* Copy all the necessary stuff from shared memory to regular memory, and protect the shared script */
     701         427 :                 if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
     702           4 :                         zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, (unique_copy_ctor_func_t) zend_class_copy_ctor);
     703             :                 }
     704             :                 /* we must first to copy all classes and then prepare functions, since functions may try to bind
     705             :                    classes - which depend on pre-bind class entries existent in the class table */
     706         427 :                 if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
     707          24 :                         zend_accel_function_hash_copy_from_shm(CG(function_table), &persistent_script->function_table);
     708             :                 }
     709             : 
     710             :                 /* Register __COMPILER_HALT_OFFSET__ constant */
     711         522 :                 if (persistent_script->compiler_halt_offset != 0 &&
     712          95 :                     persistent_script->full_path) {
     713             :                         zend_string *name;
     714          95 :                         char haltoff[] = "__COMPILER_HALT_OFFSET__";
     715             : 
     716          95 :                         name = zend_mangle_property_name(haltoff, sizeof(haltoff) - 1, persistent_script->full_path->val, persistent_script->full_path->len, 0);
     717          95 :                         if (!zend_hash_exists(EG(zend_constants), name)) {
     718           0 :                                 zend_register_long_constant(name->val, name->len, persistent_script->compiler_halt_offset, CONST_CS, 0);
     719             :                         }
     720             :                         zend_string_release(name);
     721             :                 }
     722             : 
     723         427 :                 zend_hash_destroy(&ZCG(bind_hash));
     724         427 :                 ZCG(current_persistent_script) = NULL;
     725             :         } else /* if (!from_shared_memory) */ {
     726           0 :                 if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
     727           0 :                         zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table);
     728             :                 }
     729           0 :                 if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
     730           0 :                         zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, NULL);
     731             :                 }
     732             :         }
     733             : 
     734         427 :         if (op_array->early_binding != (uint32_t)-1) {
     735           0 :                 zend_string *orig_compiled_filename = CG(compiled_filename);
     736           0 :                 CG(compiled_filename) = persistent_script->full_path;
     737           0 :                 zend_do_delayed_early_binding(op_array);
     738           0 :                 CG(compiled_filename) = orig_compiled_filename;
     739             :         }
     740             : 
     741         427 :         if (UNEXPECTED(!from_shared_memory)) {
     742           0 :                 free_persistent_script(persistent_script, 0); /* free only hashes */
     743             :         }
     744             : 
     745         427 :         return op_array;
     746             : }
     747             : 
     748             : /*
     749             :  * zend_adler32() is based on zlib implementation
     750             :  * Computes the Adler-32 checksum of a data stream
     751             :  *
     752             :  * Copyright (C) 1995-2005 Mark Adler
     753             :  * For conditions of distribution and use, see copyright notice in zlib.h
     754             :  *
     755             :  * Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
     756             :  *
     757             :  *  This software is provided 'as-is', without any express or implied
     758             :  *  warranty.  In no event will the authors be held liable for any damages
     759             :  *  arising from the use of this software.
     760             :  *
     761             :  *  Permission is granted to anyone to use this software for any purpose,
     762             :  *  including commercial applications, and to alter it and redistribute it
     763             :  *  freely, subject to the following restrictions:
     764             :  *
     765             :  *  1. The origin of this software must not be misrepresented; you must not
     766             :  *     claim that you wrote the original software. If you use this software
     767             :  *     in a product, an acknowledgment in the product documentation would be
     768             :  *     appreciated but is not required.
     769             :  *  2. Altered source versions must be plainly marked as such, and must not be
     770             :  *     misrepresented as being the original software.
     771             :  *  3. This notice may not be removed or altered from any source distribution.
     772             :  *
     773             :  */
     774             : 
     775             : #define ADLER32_BASE 65521 /* largest prime smaller than 65536 */
     776             : #define ADLER32_NMAX 5552
     777             : /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
     778             : 
     779             : #define ADLER32_DO1(buf)        {s1 += *(buf); s2 += s1;}
     780             : #define ADLER32_DO2(buf, i)     ADLER32_DO1(buf + i); ADLER32_DO1(buf + i + 1);
     781             : #define ADLER32_DO4(buf, i)     ADLER32_DO2(buf, i); ADLER32_DO2(buf, i + 2);
     782             : #define ADLER32_DO8(buf, i)     ADLER32_DO4(buf, i); ADLER32_DO4(buf, i + 4);
     783             : #define ADLER32_DO16(buf)       ADLER32_DO8(buf, 0); ADLER32_DO8(buf, 8);
     784             : 
     785         854 : unsigned int zend_adler32(unsigned int checksum, signed char *buf, uint len)
     786             : {
     787         854 :         unsigned int s1 = checksum & 0xffff;
     788         854 :         unsigned int s2 = (checksum >> 16) & 0xffff;
     789             :         signed char *end;
     790             : 
     791        1714 :         while (len >= ADLER32_NMAX) {
     792           6 :                 len -= ADLER32_NMAX;
     793           6 :                 end = buf + ADLER32_NMAX;
     794             :                 do {
     795        2082 :                         ADLER32_DO16(buf);
     796        2082 :                         buf += 16;
     797        2082 :                 } while (buf != end);
     798           6 :                 s1 %= ADLER32_BASE;
     799           6 :                 s2 %= ADLER32_BASE;
     800             :         }
     801             : 
     802         854 :         if (len) {
     803         854 :                 if (len >= 16) {
     804         854 :                         end = buf + (len & 0xfff0);
     805         854 :                         len &= 0xf;
     806             :                         do {
     807       29726 :                                 ADLER32_DO16(buf);
     808       29726 :                                 buf += 16;
     809       29726 :                         } while (buf != end);
     810             :                 }
     811         854 :                 if (len) {
     812         465 :                         end = buf + len;
     813             :                         do {
     814        3720 :                                 ADLER32_DO1(buf);
     815        3720 :                                 buf++;
     816        3720 :                         } while (buf != end);
     817             :                 }
     818         854 :                 s1 %= ADLER32_BASE;
     819         854 :                 s2 %= ADLER32_BASE;
     820             :         }
     821             : 
     822         854 :         return (s2 << 16) | s1;
     823             : }
     824             : 
     825         427 : unsigned int zend_accel_script_checksum(zend_persistent_script *persistent_script)
     826             : {
     827         427 :         signed char *mem = (signed char*)persistent_script->mem;
     828         427 :         size_t size = persistent_script->size;
     829         427 :         size_t persistent_script_check_block_size = ((char *)&(persistent_script->dynamic_members)) - (char *)persistent_script;
     830         427 :         unsigned int checksum = ADLER32_INIT;
     831             : 
     832         427 :         if (mem < (signed char*)persistent_script) {
     833           0 :                 checksum = zend_adler32(checksum, mem, (signed char*)persistent_script - mem);
     834           0 :                 size -= (signed char*)persistent_script - mem;
     835           0 :                 mem  += (signed char*)persistent_script - mem;
     836             :         }
     837             : 
     838         427 :         zend_adler32(checksum, mem, persistent_script_check_block_size);
     839         427 :         mem  += sizeof(*persistent_script);
     840         427 :         size -= sizeof(*persistent_script);
     841             : 
     842         427 :         if (size > 0) {
     843         427 :                 checksum = zend_adler32(checksum, mem, size);
     844             :         }
     845         427 :         return checksum;
     846             : }

Generated by: LCOV version 1.10

Generated at Sat, 27 Jun 2015 09:41:13 +0000 (6 days ago)

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