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_persist.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 181 370 48.9 %
Date: 2015-01-26 Functions: 11 14 78.6 %
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.h"
      23             : #include "ZendAccelerator.h"
      24             : #include "zend_persist.h"
      25             : #include "zend_extensions.h"
      26             : #include "zend_shared_alloc.h"
      27             : #include "zend_vm.h"
      28             : #include "zend_constants.h"
      29             : #include "zend_operators.h"
      30             : 
      31             : #define zend_accel_store(p, size) \
      32             :             (p = _zend_shared_memdup((void*)p, size, 1))
      33             : #define zend_accel_memdup(p, size) \
      34             :             _zend_shared_memdup((void*)p, size, 0)
      35             : 
      36             : #define zend_accel_store_string(str) do { \
      37             :                 zend_string *new_str = zend_shared_alloc_get_xlat_entry(str); \
      38             :                 if (new_str) { \
      39             :                         zend_string_release(str); \
      40             :                         str = new_str; \
      41             :                 } else { \
      42             :                 new_str = zend_accel_memdup((void*)str, _STR_HEADER_SIZE + (str)->len + 1); \
      43             :                         zend_string_release(str); \
      44             :                 str = new_str; \
      45             :                 zend_string_hash_val(str); \
      46             :                 GC_FLAGS(str) = IS_STR_INTERNED | IS_STR_PERMANENT; \
      47             :                 } \
      48             :     } while (0)
      49             : #define zend_accel_memdup_string(str) do { \
      50             :                 str = zend_accel_memdup(str, _STR_HEADER_SIZE + (str)->len + 1); \
      51             :         zend_string_hash_val(str); \
      52             :                 GC_FLAGS(str) = IS_STR_INTERNED | IS_STR_PERMANENT; \
      53             :         } while (0)
      54             : #define zend_accel_store_interned_string(str) do { \
      55             :                 if (!IS_ACCEL_INTERNED(str)) { \
      56             :                         zend_accel_store_string(str); \
      57             :                 } \
      58             :         } while (0)
      59             : #define zend_accel_memdup_interned_string(str) do { \
      60             :                 if (!IS_ACCEL_INTERNED(str)) { \
      61             :                         zend_accel_memdup_string(str); \
      62             :                 } \
      63             :         } while (0)
      64             : 
      65             : typedef void (*zend_persist_func_t)(zval*);
      66             : 
      67             : static void zend_persist_zval(zval *z);
      68             : static void zend_persist_zval_const(zval *z);
      69             : 
      70             : static const uint32_t uninitialized_bucket = {INVALID_IDX};
      71             : 
      72         927 : static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement)
      73             : {
      74             :         uint idx;
      75             :         Bucket *p;
      76             : 
      77         927 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
      78         848 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
      79         848 :                 return;
      80             :         }
      81          79 :         if (ht->u.flags & HASH_FLAG_PACKED) {
      82          10 :                 zend_accel_store(ht->arData, sizeof(Bucket) * ht->nNumUsed);
      83          10 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
      84             :         } else {
      85          69 :                 Bucket *d = (Bucket*)ZCG(mem);
      86          69 :                 uint32_t *h = (uint32_t*)(d + ht->nNumUsed);
      87             : 
      88          69 :                 ZCG(mem) = (void*)(h + ht->nTableSize);
      89          69 :                 memcpy(d, ht->arData, sizeof(Bucket) * ht->nNumUsed);
      90          69 :                 memcpy(h, ht->arHash, sizeof(uint32_t) * ht->nTableSize);
      91          69 :                 efree(ht->arData);
      92          69 :                 ht->arData = d;
      93          69 :                 ht->arHash = h;
      94             :         }
      95         237 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
      96         158 :                 p = ht->arData + idx;
      97         316 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
      98             : 
      99             :                 /* persist bucket and key */
     100         157 :                 if (p->key) {
     101         124 :                         zend_accel_store_interned_string(p->key);
     102             :                 }
     103             : 
     104             :                 /* persist the data itself */
     105         157 :                 pPersistElement(&p->val);
     106             :         }
     107             : }
     108             : 
     109           0 : static void zend_hash_persist_immutable(HashTable *ht)
     110             : {
     111             :         uint idx;
     112             :         Bucket *p;
     113             : 
     114           0 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
     115           0 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
     116           0 :                 return;
     117             :         }
     118           0 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     119           0 :                 ht->arData = zend_accel_memdup(ht->arData, sizeof(Bucket) * ht->nNumUsed);
     120           0 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
     121             :         } else {
     122           0 :                 Bucket *d = (Bucket*)ZCG(mem);
     123           0 :                 uint32_t *h = (uint32_t*)(d + ht->nNumUsed);
     124             : 
     125           0 :                 ZCG(mem) = (void*)(h + ht->nTableSize);
     126           0 :                 memcpy(d, ht->arData, sizeof(Bucket) * ht->nNumUsed);
     127           0 :                 memcpy(h, ht->arHash, sizeof(uint32_t) * ht->nTableSize);
     128           0 :                 ht->arData = d;
     129           0 :                 ht->arHash = h;
     130             :         }
     131           0 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
     132           0 :                 p = ht->arData + idx;
     133           0 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     134             : 
     135             :                 /* persist bucket and key */
     136           0 :                 if (p->key) {
     137           0 :                         zend_accel_memdup_interned_string(p->key);
     138             :                 }
     139             : 
     140             :                 /* persist the data itself */
     141           0 :                 zend_persist_zval_const(&p->val);
     142             :         }
     143             : }
     144             : 
     145           0 : static zend_ast *zend_persist_ast(zend_ast *ast)
     146             : {
     147             :         uint32_t i;
     148             :         zend_ast *node;
     149             : 
     150           0 :         if (ast->kind == ZEND_AST_ZVAL) {
     151           0 :                 zend_ast_zval *copy = zend_accel_memdup(ast, sizeof(zend_ast_zval));
     152           0 :                 zend_persist_zval(&copy->val);
     153           0 :                 node = (zend_ast *) copy;
     154           0 :         } else if (zend_ast_is_list(ast)) {
     155           0 :                 zend_ast_list *list = zend_ast_get_list(ast);
     156           0 :                 zend_ast_list *copy = zend_accel_memdup(ast,
     157             :                         sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
     158           0 :                 for (i = 0; i < list->children; i++) {
     159           0 :                         if (copy->child[i]) {
     160           0 :                                 copy->child[i] = zend_persist_ast(copy->child[i]);
     161             :                         }
     162             :                 }
     163           0 :                 node = (zend_ast *) copy;
     164             :         } else {
     165           0 :                 uint32_t children = zend_ast_get_num_children(ast);
     166           0 :                 node = zend_accel_memdup(ast, sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children);
     167           0 :                 for (i = 0; i < children; i++) {
     168           0 :                         if (node->child[i]) {
     169           0 :                                 node->child[i] = zend_persist_ast(node->child[i]);
     170             :                         }
     171             :                 }
     172             :         }
     173             : 
     174           0 :         efree(ast);
     175           0 :         return node;
     176             : }
     177             : 
     178        3105 : static void zend_persist_zval(zval *z)
     179             : {
     180             :         zend_uchar flags;
     181             :         void *new_ptr;
     182             : 
     183        3105 :         switch (Z_TYPE_P(z)) {
     184             :                 case IS_STRING:
     185             :                 case IS_CONSTANT:
     186        2406 :                         flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
     187        2406 :                         zend_accel_store_interned_string(Z_STR_P(z));
     188        2406 :                         Z_GC_FLAGS_P(z) |= flags;
     189        2406 :                         Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
     190        2406 :                         break;
     191             :                 case IS_ARRAY:
     192          67 :                         new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
     193          67 :                         if (new_ptr) {
     194           0 :                                 Z_ARR_P(z) = new_ptr;
     195           0 :                                 Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
     196             :                         } else {
     197          67 :                                 if (Z_IMMUTABLE_P(z)) {
     198           0 :                                         Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array));
     199           0 :                                         zend_hash_persist_immutable(Z_ARRVAL_P(z));
     200             :                                 } else {
     201          67 :                                         GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
     202          67 :                                         zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
     203          67 :                                         zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
     204             :                                         /* make immutable array */
     205          67 :                                         Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
     206          67 :                                         GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
     207          67 :                                         Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     208             :                                 }
     209             :                         }
     210          67 :                         break;
     211             :                 case IS_REFERENCE:
     212           0 :                         new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z));
     213           0 :                         if (new_ptr) {
     214           0 :                                 Z_REF_P(z) = new_ptr;
     215             :                         } else {
     216           0 :                                 zend_accel_store(Z_REF_P(z), sizeof(zend_reference));
     217           0 :                                 zend_persist_zval(Z_REFVAL_P(z));
     218             :                         }
     219           0 :                         break;
     220             :                 case IS_CONSTANT_AST:
     221           0 :                         new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
     222           0 :                         if (new_ptr) {
     223           0 :                                 Z_AST_P(z) = new_ptr;
     224             :                         } else {
     225           0 :                                 zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
     226           0 :                                 Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
     227             :                         }
     228             :                         break;
     229             :         }
     230        3105 : }
     231             : 
     232           0 : static void zend_persist_zval_const(zval *z)
     233             : {
     234             :         zend_uchar flags;
     235             :         void *new_ptr;
     236             : 
     237           0 :         switch (Z_TYPE_P(z)) {
     238             :                 case IS_STRING:
     239             :                 case IS_CONSTANT:
     240           0 :                         flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
     241           0 :                         zend_accel_memdup_interned_string(Z_STR_P(z));
     242           0 :                         Z_GC_FLAGS_P(z) |= flags;
     243           0 :                         Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
     244           0 :                         break;
     245             :                 case IS_ARRAY:
     246           0 :                         new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
     247           0 :                         if (new_ptr) {
     248           0 :                                 Z_ARR_P(z) = new_ptr;
     249           0 :                                 Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
     250             :                         } else {
     251           0 :                                 if (Z_IMMUTABLE_P(z)) {
     252           0 :                                         Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array));
     253           0 :                                         zend_hash_persist_immutable(Z_ARRVAL_P(z));
     254             :                                 } else {
     255           0 :                                         GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
     256           0 :                                         zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
     257           0 :                                         zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
     258             :                                         /* make immutable array */
     259           0 :                                         Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
     260           0 :                                         GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
     261           0 :                                         Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     262             :                                 }
     263             :                         }
     264           0 :                         break;
     265             :                 case IS_REFERENCE:
     266           0 :                         new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z));
     267           0 :                         if (new_ptr) {
     268           0 :                                 Z_REF_P(z) = new_ptr;
     269             :                         } else {
     270           0 :                                 zend_accel_store(Z_REF_P(z), sizeof(zend_reference));
     271           0 :                                 zend_persist_zval(Z_REFVAL_P(z));
     272             :                         }
     273           0 :                         break;
     274             :                 case IS_CONSTANT_AST:
     275           0 :                         new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
     276           0 :                         if (new_ptr) {
     277           0 :                                 Z_AST_P(z) = new_ptr;
     278             :                         } else {
     279           0 :                                 zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
     280           0 :                                 Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
     281             :                         }
     282             :                         break;
     283             :         }
     284           0 : }
     285             : 
     286         451 : static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script)
     287             : {
     288         451 :         int already_stored = 0;
     289             :         zend_op *persist_ptr;
     290         451 :         zval *orig_literals = NULL;
     291             : 
     292         451 :         if (op_array->type != ZEND_USER_FUNCTION) {
     293           0 :                 return;
     294             :         }
     295             : 
     296         451 :         if (--(*op_array->refcount) == 0) {
     297         451 :                 efree(op_array->refcount);
     298             :         }
     299         451 :         op_array->refcount = NULL;
     300             : 
     301         451 :         if (main_persistent_script) {
     302         422 :                 zend_execute_data *orig_execute_data = EG(current_execute_data);
     303             :                 zend_execute_data fake_execute_data;
     304             :                 zval *offset;
     305             : 
     306         422 :                 memset(&fake_execute_data, 0, sizeof(fake_execute_data));
     307         422 :                 fake_execute_data.func = (zend_function*)op_array;
     308         422 :                 EG(current_execute_data) = &fake_execute_data;
     309         422 :                 if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
     310          95 :                         main_persistent_script->compiler_halt_offset = Z_LVAL_P(offset);
     311             :                 }
     312         422 :                 EG(current_execute_data) = orig_execute_data;
     313             :         }
     314             : 
     315         451 :         if (op_array->static_variables) {
     316          13 :                 zend_hash_persist(op_array->static_variables, zend_persist_zval);
     317          13 :                 zend_accel_store(op_array->static_variables, sizeof(HashTable));
     318             :         }
     319             : 
     320         451 :         if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) {
     321           0 :                 already_stored = 1;
     322             :         }
     323             : 
     324         451 :         if (op_array->literals) {
     325         451 :                 if (already_stored) {
     326           0 :                         orig_literals = zend_shared_alloc_get_xlat_entry(op_array->literals);
     327             :                         ZEND_ASSERT(orig_literals != NULL);
     328           0 :                         op_array->literals = orig_literals;
     329             :                 } else {
     330         451 :                         zval *p = zend_accel_memdup(op_array->literals, sizeof(zval) * op_array->last_literal);
     331         451 :                         zval *end = p + op_array->last_literal;
     332         451 :                         orig_literals = op_array->literals;
     333         451 :                         op_array->literals = p;
     334        3880 :                         while (p < end) {
     335        2978 :                                 zend_persist_zval(p);
     336        2978 :                                 p++;
     337             :                         }
     338         451 :                         efree(orig_literals);
     339             :                 }
     340             :         }
     341             : 
     342         451 :         if (already_stored) {
     343           0 :                 persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
     344             :                 ZEND_ASSERT(persist_ptr != NULL);
     345           0 :                 op_array->opcodes = persist_ptr;
     346             :         } else {
     347         451 :                 zend_op *new_opcodes = zend_accel_memdup(op_array->opcodes, sizeof(zend_op) * op_array->last);
     348             : #if ZEND_USE_ABS_CONST_ADDR || ZEND_USE_ABS_JMP_ADDR
     349             :                 zend_op *opline = new_opcodes;
     350             :                 zend_op *end = new_opcodes + op_array->last;
     351             :                 int offset = 0;
     352             : 
     353             :                 for (; opline < end ; opline++, offset++) {
     354             : # if ZEND_USE_ABS_CONST_ADDR
     355             :                         if (ZEND_OP1_TYPE(opline) == IS_CONST) {
     356             :                                 opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals));
     357             :                         }
     358             :                         if (ZEND_OP2_TYPE(opline) == IS_CONST) {
     359             :                                 opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals));
     360             :                         }
     361             : # endif
     362             : # if ZEND_USE_ABS_JMP_ADDR
     363             :                         if (ZEND_DONE_PASS_TWO(op_array)) {
     364             :                                 /* fix jumps to point to new array */
     365             :                                 switch (opline->opcode) {
     366             :                                         case ZEND_JMP:
     367             :                                         case ZEND_GOTO:
     368             :                                         case ZEND_FAST_CALL:
     369             :                                                 ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes];
     370             :                                                 break;
     371             :                                         case ZEND_JMPZNZ:
     372             :                                                 /* relative extended_value don't have to be changed */
     373             :                                                 /* break omitted intentionally */
     374             :                                         case ZEND_JMPZ:
     375             :                                         case ZEND_JMPNZ:
     376             :                                         case ZEND_JMPZ_EX:
     377             :                                         case ZEND_JMPNZ_EX:
     378             :                                         case ZEND_JMP_SET:
     379             :                                         case ZEND_COALESCE:
     380             :                                         case ZEND_NEW:
     381             :                                         case ZEND_FE_RESET:
     382             :                                         case ZEND_FE_FETCH:
     383             :                                                 ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes];
     384             :                                                 break;
     385             :                                 }
     386             :                         }
     387             : # endif
     388             :                 }
     389             : #endif
     390             : 
     391         451 :                 efree(op_array->opcodes);
     392         451 :                 op_array->opcodes = new_opcodes;
     393             : 
     394         451 :                 if (op_array->run_time_cache) {
     395           0 :                         efree(op_array->run_time_cache);
     396           0 :                         op_array->run_time_cache = NULL;
     397             :                 }
     398             :         }
     399             : 
     400         451 :         if (op_array->function_name && !IS_ACCEL_INTERNED(op_array->function_name)) {
     401             :                 zend_string *new_name;
     402           0 :                 if (already_stored) {
     403           0 :                         new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name);
     404             :                         ZEND_ASSERT(new_name != NULL);
     405           0 :                         op_array->function_name = new_name;
     406             :                 } else {
     407           0 :                         zend_accel_store_string(op_array->function_name);
     408             :                 }
     409             :         }
     410             : 
     411         451 :         if (op_array->filename) {
     412             :                 /* do not free! PHP has centralized filename storage, compiler will free it */
     413         902 :                 zend_accel_memdup_string(op_array->filename);
     414             :         }
     415             : 
     416         451 :         if (op_array->arg_info) {
     417          25 :                 if (already_stored) {
     418           0 :                         zend_arg_info *new_ptr = zend_shared_alloc_get_xlat_entry(op_array->arg_info);
     419             :                         ZEND_ASSERT(new_ptr != NULL);
     420           0 :                         op_array->arg_info = new_ptr;
     421             :                 } else {
     422             :                         uint32_t i, num_args;
     423             : 
     424          25 :                         num_args = op_array->num_args;
     425          25 :                         if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
     426           0 :                                 num_args++;
     427             :                         }
     428          25 :                         zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * num_args);
     429          55 :                         for (i = 0; i < num_args; i++) {
     430          30 :                                 if (op_array->arg_info[i].name) {
     431          30 :                                         zend_accel_store_interned_string(op_array->arg_info[i].name);
     432             :                                 }
     433          30 :                                 if (op_array->arg_info[i].class_name) {
     434           0 :                                         zend_accel_store_interned_string(op_array->arg_info[i].class_name);
     435             :                                 }
     436             :                         }
     437             :                 }
     438             :         }
     439             : 
     440         451 :         if (op_array->brk_cont_array) {
     441          17 :                 zend_accel_store(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont);
     442             :         }
     443             : 
     444         451 :         if (op_array->scope) {
     445           5 :                 op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
     446             :         }
     447             : 
     448         451 :         if (op_array->doc_comment) {
     449           0 :                 if (ZCG(accel_directives).save_comments) {
     450           0 :                         if (already_stored) {
     451           0 :                                 op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment);
     452             :                                 ZEND_ASSERT(op_array->doc_comment != NULL);
     453             :                         } else {
     454           0 :                                 zend_accel_store_string(op_array->doc_comment);
     455             :                         }
     456             :                 } else {
     457           0 :                         if (!already_stored) {
     458           0 :                                 zend_string_release(op_array->doc_comment);
     459             :                         }
     460           0 :                         op_array->doc_comment = NULL;
     461             :                 }
     462             :         }
     463             : 
     464         451 :         if (op_array->try_catch_array) {
     465           8 :                 zend_accel_store(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
     466             :         }
     467             : 
     468         451 :         if (op_array->vars) {
     469          71 :                 if (already_stored) {
     470           0 :                         persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars);
     471             :                         ZEND_ASSERT(persist_ptr != NULL);
     472           0 :                         op_array->vars = (zend_string**)persist_ptr;
     473             :                 } else {
     474             :                         int i;
     475          71 :                         zend_accel_store(op_array->vars, sizeof(zend_string*) * op_array->last_var);
     476         239 :                         for (i = 0; i < op_array->last_var; i++) {
     477         168 :                                 zend_accel_store_interned_string(op_array->vars[i]);
     478             :                         }
     479             :                 }
     480             :         }
     481             : 
     482             :         /* "prototype" may be undefined if "scope" isn't set */
     483         451 :         if (op_array->scope && op_array->prototype) {
     484           0 :                 if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) {
     485           0 :                         op_array->prototype = (union _zend_function*)persist_ptr;
     486             :                         /* we use refcount to show that op_array is referenced from several places */
     487           0 :                         op_array->prototype->op_array.refcount++;
     488             :                 }
     489             :         } else {
     490         451 :                 op_array->prototype = NULL;
     491             :         }
     492             : }
     493             : 
     494          29 : static void zend_persist_op_array(zval *zv)
     495             : {
     496          29 :         memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_op_array));
     497          29 :         zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     498          29 :         Z_PTR_P(zv) = ZCG(arena_mem);
     499          29 :         ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_op_array)));
     500          29 :         zend_persist_op_array_ex(Z_PTR_P(zv), NULL);
     501          29 : }
     502             : 
     503           2 : static void zend_persist_property_info(zval *zv)
     504             : {
     505             :         zend_property_info *prop;
     506             : 
     507           2 :         memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_property_info));
     508           2 :         zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     509           2 :         prop = Z_PTR_P(zv) = ZCG(arena_mem);
     510           2 :         ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_property_info)));
     511           2 :         zend_accel_store_interned_string(prop->name);
     512           2 :         if (prop->doc_comment) {
     513           0 :                 if (ZCG(accel_directives).save_comments) {
     514           0 :                         zend_accel_store_string(prop->doc_comment);
     515             :                 } else {
     516           0 :                         if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) {
     517           0 :                                 zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment);
     518             :                         }
     519           0 :                         zend_string_release(prop->doc_comment);
     520           0 :                         prop->doc_comment = NULL;
     521             :                 }
     522             :         }
     523           2 : }
     524             : 
     525           1 : static void zend_persist_class_entry(zval *zv)
     526             : {
     527           1 :         zend_class_entry *ce = Z_PTR_P(zv);
     528             : 
     529           1 :         if (ce->type == ZEND_USER_CLASS) {
     530           1 :                 memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_class_entry));
     531           1 :                 zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     532           1 :                 ce = Z_PTR_P(zv) = ZCG(arena_mem);
     533           1 :                 ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_class_entry)));
     534           1 :                 zend_accel_store_interned_string(ce->name);
     535           1 :                 zend_hash_persist(&ce->function_table, zend_persist_op_array);
     536           1 :                 if (ce->default_properties_table) {
     537             :                     int i;
     538             : 
     539           0 :                         zend_accel_store(ce->default_properties_table, sizeof(zval) * ce->default_properties_count);
     540           0 :                         for (i = 0; i < ce->default_properties_count; i++) {
     541           0 :                                 zend_persist_zval(&ce->default_properties_table[i]);
     542             :                         }
     543             :                 }
     544           1 :                 if (ce->default_static_members_table) {
     545             :                     int i;
     546             : 
     547           1 :                         zend_accel_store(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count);
     548           3 :                         for (i = 0; i < ce->default_static_members_count; i++) {
     549           2 :                                 zend_persist_zval(&ce->default_static_members_table[i]);
     550             :                         }
     551             :                 }
     552           1 :                 ce->static_members_table = NULL;
     553             : 
     554           1 :                 zend_hash_persist(&ce->constants_table, zend_persist_zval);
     555             : 
     556           1 :                 if (ZEND_CE_FILENAME(ce)) {
     557             :                         /* do not free! PHP has centralized filename storage, compiler will free it */
     558           2 :                         zend_accel_memdup_string(ZEND_CE_FILENAME(ce));
     559             :                 }
     560           1 :                 if (ZEND_CE_DOC_COMMENT(ce)) {
     561           0 :                         if (ZCG(accel_directives).save_comments) {
     562           0 :                                 zend_accel_store_string(ZEND_CE_DOC_COMMENT(ce));
     563             :                         } else {
     564           0 :                                 if (!zend_shared_alloc_get_xlat_entry(ZEND_CE_DOC_COMMENT(ce))) {
     565           0 :                                         zend_shared_alloc_register_xlat_entry(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT(ce));
     566           0 :                                         zend_string_release(ZEND_CE_DOC_COMMENT(ce));
     567             :                                 }
     568           0 :                                 ZEND_CE_DOC_COMMENT(ce) = NULL;
     569             :                         }
     570             :                 }
     571           1 :                 zend_hash_persist(&ce->properties_info, zend_persist_property_info);
     572           1 :                 if (ce->num_interfaces && ce->interfaces) {
     573           0 :                         efree(ce->interfaces);
     574             :                 }
     575           1 :                 ce->interfaces = NULL; /* will be filled in on fetch */
     576             : 
     577           1 :                 if (ce->num_traits && ce->traits) {
     578           0 :                         efree(ce->traits);
     579             :                 }
     580           1 :                 ce->traits = NULL;
     581             : 
     582           1 :                 if (ce->trait_aliases) {
     583           0 :                         int i = 0;
     584           0 :                         while (ce->trait_aliases[i]) {
     585           0 :                                 if (ce->trait_aliases[i]->trait_method) {
     586           0 :                                         if (ce->trait_aliases[i]->trait_method->method_name) {
     587           0 :                                                 zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->method_name);
     588             :                                         }
     589           0 :                                         if (ce->trait_aliases[i]->trait_method->class_name) {
     590           0 :                                                 zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->class_name);
     591             :                                         }
     592           0 :                                         ce->trait_aliases[i]->trait_method->ce = NULL;
     593           0 :                                         zend_accel_store(ce->trait_aliases[i]->trait_method,
     594             :                                                 sizeof(zend_trait_method_reference));
     595             :                                 }
     596             : 
     597           0 :                                 if (ce->trait_aliases[i]->alias) {
     598           0 :                                         zend_accel_store_interned_string(ce->trait_aliases[i]->alias);
     599             :                                 }
     600             : 
     601           0 :                                 zend_accel_store(ce->trait_aliases[i], sizeof(zend_trait_alias));
     602           0 :                                 i++;
     603             :                         }
     604             : 
     605           0 :                         zend_accel_store(ce->trait_aliases, sizeof(zend_trait_alias*) * (i + 1));
     606             :                 }
     607             : 
     608           1 :                 if (ce->trait_precedences) {
     609           0 :                         int i = 0;
     610             : 
     611           0 :                         while (ce->trait_precedences[i]) {
     612           0 :                                 zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->method_name);
     613           0 :                                 zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->class_name);
     614           0 :                                 ce->trait_precedences[i]->trait_method->ce = NULL;
     615           0 :                                 zend_accel_store(ce->trait_precedences[i]->trait_method,
     616             :                                         sizeof(zend_trait_method_reference));
     617             : 
     618           0 :                                 if (ce->trait_precedences[i]->exclude_from_classes) {
     619           0 :                                         int j = 0;
     620             : 
     621           0 :                                         while (ce->trait_precedences[i]->exclude_from_classes[j].class_name) {
     622           0 :                                                 zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_from_classes[j].class_name);
     623           0 :                                                 j++;
     624             :                                         }
     625           0 :                                         zend_accel_store(ce->trait_precedences[i]->exclude_from_classes,
     626             :                                                 sizeof(zend_class_entry*) * (j + 1));
     627             :                                 }
     628             : 
     629           0 :                                 zend_accel_store(ce->trait_precedences[i], sizeof(zend_trait_precedence));
     630           0 :                                 i++;
     631             :                         }
     632           0 :                         zend_accel_store(
     633             :                                 ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1));
     634             :                 }
     635             :         }
     636           1 : }
     637             : 
     638           2 : static int zend_update_property_info_ce(zval *zv)
     639             : {
     640           2 :         zend_property_info *prop = Z_PTR_P(zv);
     641             : 
     642           2 :         prop->ce = zend_shared_alloc_get_xlat_entry(prop->ce);
     643           2 :         return 0;
     644             : }
     645             : 
     646           1 : static int zend_update_parent_ce(zval *zv)
     647             : {
     648           1 :         zend_class_entry *ce = Z_PTR_P(zv);
     649             : 
     650           1 :         if (ce->parent) {
     651           0 :                 ce->parent = zend_shared_alloc_get_xlat_entry(ce->parent);
     652             :                 /* We use refcount to show if the class is used as a parent */
     653           0 :                 ce->parent->refcount++;
     654             :         }
     655             : 
     656             :         /* update methods */
     657           1 :         if (ce->constructor) {
     658           0 :                 ce->constructor = zend_shared_alloc_get_xlat_entry(ce->constructor);
     659             :                 /* we use refcount to show that op_array is referenced from several places */
     660           0 :                 ce->constructor->op_array.refcount++;
     661             :         }
     662           1 :         if (ce->destructor) {
     663           0 :                 ce->destructor = zend_shared_alloc_get_xlat_entry(ce->destructor);
     664           0 :                 ce->destructor->op_array.refcount++;
     665             :         }
     666           1 :         if (ce->clone) {
     667           0 :                 ce->clone = zend_shared_alloc_get_xlat_entry(ce->clone);
     668           0 :                 ce->clone->op_array.refcount++;
     669             :         }
     670           1 :         if (ce->__get) {
     671           0 :                 ce->__get = zend_shared_alloc_get_xlat_entry(ce->__get);
     672           0 :                 ce->__get->op_array.refcount++;
     673             :         }
     674           1 :         if (ce->__set) {
     675           0 :                 ce->__set = zend_shared_alloc_get_xlat_entry(ce->__set);
     676           0 :                 ce->__set->op_array.refcount++;
     677             :         }
     678           1 :         if (ce->__call) {
     679           0 :                 ce->__call = zend_shared_alloc_get_xlat_entry(ce->__call);
     680           0 :                 ce->__call->op_array.refcount++;
     681             :         }
     682           1 :         if (ce->serialize_func) {
     683           0 :                 ce->serialize_func = zend_shared_alloc_get_xlat_entry(ce->serialize_func);
     684           0 :                 ce->serialize_func->op_array.refcount++;
     685             :         }
     686           1 :         if (ce->unserialize_func) {
     687           0 :                 ce->unserialize_func = zend_shared_alloc_get_xlat_entry(ce->unserialize_func);
     688           0 :                 ce->unserialize_func->op_array.refcount++;
     689             :         }
     690           1 :         if (ce->__isset) {
     691           0 :                 ce->__isset = zend_shared_alloc_get_xlat_entry(ce->__isset);
     692           0 :                 ce->__isset->op_array.refcount++;
     693             :         }
     694           1 :         if (ce->__unset) {
     695           0 :                 ce->__unset = zend_shared_alloc_get_xlat_entry(ce->__unset);
     696           0 :                 ce->__unset->op_array.refcount++;
     697             :         }
     698           1 :         if (ce->__tostring) {
     699           0 :                 ce->__tostring = zend_shared_alloc_get_xlat_entry(ce->__tostring);
     700           0 :                 ce->__tostring->op_array.refcount++;
     701             :         }
     702           1 :         if (ce->__callstatic) {
     703           0 :                 ce->__callstatic = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
     704           0 :                 ce->__callstatic->op_array.refcount++;
     705             :         }
     706           1 :         if (ce->__debugInfo) {
     707           0 :                 ce->__debugInfo = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
     708           0 :                 ce->__debugInfo->op_array.refcount++;
     709             :         }
     710           1 :         zend_hash_apply(&ce->properties_info, (apply_func_t) zend_update_property_info_ce);
     711           1 :         return 0;
     712             : }
     713             : 
     714         422 : static void zend_accel_persist_class_table(HashTable *class_table)
     715             : {
     716         422 :     zend_hash_persist(class_table, zend_persist_class_entry);
     717         422 :         zend_hash_apply(class_table, (apply_func_t) zend_update_parent_ce);
     718         422 : }
     719             : 
     720         422 : zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length)
     721             : {
     722         422 :         script->mem = ZCG(mem);
     723             : 
     724         422 :         zend_shared_alloc_clear_xlat_table();
     725             : 
     726         422 :         zend_accel_store(script, sizeof(zend_persistent_script));
     727         422 :         *key = zend_accel_memdup(*key, key_length + 1);
     728        1266 :         zend_accel_store_string(script->full_path);
     729             : 
     730         422 :         script->arena_mem = ZCG(arena_mem) = ZCG(mem);
     731         422 :         ZCG(mem) = (void*)((char*)ZCG(mem) + script->arena_size);
     732             : 
     733         422 :         zend_accel_persist_class_table(&script->class_table);
     734         422 :         zend_hash_persist(&script->function_table, zend_persist_op_array);
     735         422 :         zend_persist_op_array_ex(&script->main_op_array, script);
     736             : 
     737         422 :         return script;
     738             : }
     739             : 
     740         422 : int zend_accel_script_persistable(zend_persistent_script *script)
     741             : {
     742         422 :         return 1;
     743             : }

Generated by: LCOV version 1.10

Generated at Mon, 26 Jan 2015 14:46:48 +0000 (3 days ago)

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