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: 180 368 48.9 %
Date: 2014-09-27 Functions: 11 14 78.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend OPcache                                                         |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Zeev Suraski <zeev@zend.com>                                |
      17             :    |          Stanislav Malyshev <stas@zend.com>                          |
      18             :    |          Dmitry Stogov <dmitry@zend.com>                             |
      19             :    +----------------------------------------------------------------------+
      20             : */
      21             : 
      22             : #include "zend.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 TSRMLS_CC))
      33             : #define zend_accel_memdup(p, size) \
      34             :             _zend_shared_memdup((void*)p, size, 0 TSRMLS_CC)
      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* TSRMLS_DC);
      66             : 
      67             : static void zend_persist_zval(zval *z TSRMLS_DC);
      68             : static void zend_persist_zval_const(zval *z TSRMLS_DC);
      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 TSRMLS_DC)
      73             : {
      74             :         uint idx;
      75             :         Bucket *p;
      76             : 
      77         927 :         if (!ht->nTableMask) {
      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         236 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
      96         157 :                 p = ht->arData + idx;
      97         314 :                 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 TSRMLS_CC);
     106             :         }
     107             : }
     108             : 
     109           0 : static void zend_hash_persist_immutable(HashTable *ht TSRMLS_DC)
     110             : {
     111             :         uint idx;
     112             :         Bucket *p;
     113             : 
     114           0 :         if (!ht->nTableMask) {
     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 TSRMLS_CC);
     142             :         }
     143             : }
     144             : 
     145           0 : static zend_ast *zend_persist_ast(zend_ast *ast TSRMLS_DC)
     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 TSRMLS_CC);
     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] TSRMLS_CC);
     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] TSRMLS_CC);
     170             :                         }
     171             :                 }
     172             :         }
     173             : 
     174           0 :         efree(ast);
     175           0 :         return node;
     176             : }
     177             : 
     178        3073 : static void zend_persist_zval(zval *z TSRMLS_DC)
     179             : {
     180             :         zend_uchar flags;
     181             :         void *new_ptr;
     182             : 
     183        3073 :         switch (Z_TYPE_P(z)) {
     184             :                 case IS_STRING:
     185             :                 case IS_CONSTANT:
     186        2374 :                         flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
     187        2374 :                         zend_accel_store_interned_string(Z_STR_P(z));
     188        2374 :                         Z_GC_FLAGS_P(z) |= flags;
     189        2374 :                         Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
     190        2374 :                         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) TSRMLS_CC);
     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 TSRMLS_CC);
     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) TSRMLS_CC);
     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) TSRMLS_CC);
     227             :                         }
     228             :                         break;
     229             :         }
     230        3073 : }
     231             : 
     232           0 : static void zend_persist_zval_const(zval *z TSRMLS_DC)
     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) TSRMLS_CC);
     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 TSRMLS_CC);
     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) TSRMLS_CC);
     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) TSRMLS_CC);
     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 TSRMLS_DC)
     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 TSRMLS_CC)) != 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 TSRMLS_CC);
     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        3848 :                         while (p < end) {
     335        2946 :                                 zend_persist_zval(p TSRMLS_CC);
     336        2946 :                                 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         451 :                 zend_op *opline = new_opcodes;
     349         451 :                 zend_op *end = new_opcodes + op_array->last;
     350         451 :                 int offset = 0;
     351             : 
     352        6184 :                 for (; opline < end ; opline++, offset++) {
     353        5733 :                         if (ZEND_OP1_TYPE(opline) == IS_CONST) {
     354        2043 :                                 opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals));
     355             :                         }
     356        5733 :                         if (ZEND_OP2_TYPE(opline) == IS_CONST) {
     357        1423 :                                 opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals));
     358             :                         }
     359             : 
     360        5733 :                         if (ZEND_DONE_PASS_TWO(op_array)) {
     361             :                                 /* fix jumps to point to new array */
     362        5733 :                                 switch (opline->opcode) {
     363             :                                         case ZEND_JMP:
     364             :                                         case ZEND_GOTO:
     365             :                                         case ZEND_FAST_CALL:
     366          22 :                                                 ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes];
     367          22 :                                                 break;
     368             :                                         case ZEND_JMPZNZ:
     369             :                                                 /* relative extended_value don't have to be changed */
     370             :                                                 /* break omitted intentionally */
     371             :                                         case ZEND_JMPZ:
     372             :                                         case ZEND_JMPNZ:
     373             :                                         case ZEND_JMPZ_EX:
     374             :                                         case ZEND_JMPNZ_EX:
     375             :                                         case ZEND_JMP_SET:
     376             :                                         case ZEND_NEW:
     377             :                                         case ZEND_FE_RESET:
     378             :                                         case ZEND_FE_FETCH:
     379         197 :                                                 ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes];
     380             :                                                 break;
     381             :                                 }
     382             :                         }
     383             :                 }
     384             : 
     385         451 :                 efree(op_array->opcodes);
     386         451 :                 op_array->opcodes = new_opcodes;
     387             : 
     388         451 :                 if (op_array->run_time_cache) {
     389           0 :                         efree(op_array->run_time_cache);
     390           0 :                         op_array->run_time_cache = NULL;
     391             :                 }
     392             :         }
     393             : 
     394         451 :         if (op_array->function_name && !IS_ACCEL_INTERNED(op_array->function_name)) {
     395             :                 zend_string *new_name;
     396           0 :                 if (already_stored) {
     397           0 :                         new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name);
     398             :                         ZEND_ASSERT(new_name != NULL);
     399           0 :                         op_array->function_name = new_name;
     400             :                 } else {
     401           0 :                         zend_accel_store_string(op_array->function_name);
     402             :                 }
     403             :         }
     404             : 
     405         451 :         if (op_array->filename) {
     406             :                 /* do not free! PHP has centralized filename storage, compiler will free it */
     407         902 :                 zend_accel_memdup_string(op_array->filename);
     408             :         }
     409             : 
     410         451 :         if (op_array->arg_info) {
     411          25 :                 if (already_stored) {
     412           0 :                         zend_arg_info *new_ptr = zend_shared_alloc_get_xlat_entry(op_array->arg_info);
     413             :                         ZEND_ASSERT(new_ptr != NULL);
     414           0 :                         op_array->arg_info = new_ptr;
     415             :                 } else {
     416             :                         uint32_t i;
     417             : 
     418          25 :                         zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args);
     419          55 :                         for (i = 0; i < op_array->num_args; i++) {
     420          30 :                                 if (op_array->arg_info[i].name) {
     421             : //???                                   zend_accel_store_interned_string(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1);
     422          30 :                                         zend_accel_store(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1);
     423             :                                 }
     424          30 :                                 if (op_array->arg_info[i].class_name) {
     425             : //???                                   zend_accel_store_interned_string(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1);
     426           0 :                                         zend_accel_store(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1);
     427             :                                 }
     428             :                         }
     429             :                 }
     430             :         }
     431             : 
     432         451 :         if (op_array->brk_cont_array) {
     433           2 :                 zend_accel_store(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont);
     434             :         }
     435             : 
     436         451 :         if (op_array->scope) {
     437           5 :                 op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
     438             :         }
     439             : 
     440         451 :         if (op_array->doc_comment) {
     441           0 :                 if (ZCG(accel_directives).save_comments) {
     442           0 :                         if (already_stored) {
     443           0 :                                 op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment);
     444             :                                 ZEND_ASSERT(op_array->doc_comment != NULL);
     445             :                         } else {
     446           0 :                                 zend_accel_store_string(op_array->doc_comment);
     447             :                         }
     448             :                 } else {
     449           0 :                         if (!already_stored) {
     450           0 :                                 zend_string_release(op_array->doc_comment);
     451             :                         }
     452           0 :                         op_array->doc_comment = NULL;
     453             :                 }
     454             :         }
     455             : 
     456         451 :         if (op_array->try_catch_array) {
     457           8 :                 zend_accel_store(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
     458             :         }
     459             : 
     460         451 :         if (op_array->vars) {
     461          71 :                 if (already_stored) {
     462           0 :                         persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars);
     463             :                         ZEND_ASSERT(persist_ptr != NULL);
     464           0 :                         op_array->vars = (zend_string**)persist_ptr;
     465             :                 } else {
     466             :                         int i;
     467          71 :                         zend_accel_store(op_array->vars, sizeof(zend_string*) * op_array->last_var);
     468         239 :                         for (i = 0; i < op_array->last_var; i++) {
     469         168 :                                 zend_accel_store_interned_string(op_array->vars[i]);
     470             :                         }
     471             :                 }
     472             :         }
     473             : 
     474             :         /* "prototype" may be undefined if "scope" isn't set */
     475         451 :         if (op_array->scope && op_array->prototype) {
     476           0 :                 if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) {
     477           0 :                         op_array->prototype = (union _zend_function*)persist_ptr;
     478             :                         /* we use refcount to show that op_array is referenced from several places */
     479           0 :                         op_array->prototype->op_array.refcount++;
     480             :                 }
     481             :         } else {
     482         451 :                 op_array->prototype = NULL;
     483             :         }
     484             : }
     485             : 
     486          29 : static void zend_persist_op_array(zval *zv TSRMLS_DC)
     487             : {
     488          29 :         Z_PTR_P(zv) = zend_accel_memdup(Z_PTR_P(zv), sizeof(zend_op_array));
     489          29 :         zend_persist_op_array_ex(Z_PTR_P(zv), NULL TSRMLS_CC);
     490          29 : }
     491             : 
     492           2 : static void zend_persist_property_info(zval *zv TSRMLS_DC)
     493             : {
     494             :         zend_property_info *prop;
     495             : 
     496           2 :         prop = Z_PTR_P(zv) = zend_accel_memdup(Z_PTR_P(zv), sizeof(zend_property_info));
     497           2 :         zend_accel_store_interned_string(prop->name);
     498           2 :         if (prop->doc_comment) {
     499           0 :                 if (ZCG(accel_directives).save_comments) {
     500           0 :                         zend_accel_store_string(prop->doc_comment);
     501             :                 } else {
     502           0 :                         if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) {
     503           0 :                                 zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment);
     504             :                         }
     505           0 :                         zend_string_release(prop->doc_comment);
     506           0 :                         prop->doc_comment = NULL;
     507             :                 }
     508             :         }
     509           2 : }
     510             : 
     511           1 : static void zend_persist_class_entry(zval *zv TSRMLS_DC)
     512             : {
     513           1 :         zend_class_entry *ce = Z_PTR_P(zv);
     514             : 
     515           1 :         if (ce->type == ZEND_USER_CLASS) {
     516           1 :                 ce = Z_PTR_P(zv) = zend_accel_memdup(ce, sizeof(zend_class_entry));
     517           1 :                 zend_accel_store_interned_string(ce->name);
     518           1 :                 zend_hash_persist(&ce->function_table, zend_persist_op_array TSRMLS_CC);
     519           1 :                 if (ce->default_properties_table) {
     520             :                     int i;
     521             : 
     522           0 :                         zend_accel_store(ce->default_properties_table, sizeof(zval) * ce->default_properties_count);
     523           0 :                         for (i = 0; i < ce->default_properties_count; i++) {
     524           0 :                                 zend_persist_zval(&ce->default_properties_table[i] TSRMLS_CC);
     525             :                         }
     526             :                 }
     527           1 :                 if (ce->default_static_members_table) {
     528             :                     int i;
     529             : 
     530           1 :                         zend_accel_store(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count);
     531           3 :                         for (i = 0; i < ce->default_static_members_count; i++) {
     532           2 :                                 zend_persist_zval(&ce->default_static_members_table[i] TSRMLS_CC);
     533             :                         }
     534             :                 }
     535           1 :                 ce->static_members_table = NULL;
     536             : 
     537           1 :                 zend_hash_persist(&ce->constants_table, zend_persist_zval TSRMLS_CC);
     538             : 
     539           1 :                 if (ZEND_CE_FILENAME(ce)) {
     540             :                         /* do not free! PHP has centralized filename storage, compiler will free it */
     541           2 :                         zend_accel_memdup_string(ZEND_CE_FILENAME(ce));
     542             :                 }
     543           1 :                 if (ZEND_CE_DOC_COMMENT(ce)) {
     544           0 :                         if (ZCG(accel_directives).save_comments) {
     545           0 :                                 zend_accel_store_string(ZEND_CE_DOC_COMMENT(ce));
     546             :                         } else {
     547           0 :                                 if (!zend_shared_alloc_get_xlat_entry(ZEND_CE_DOC_COMMENT(ce))) {
     548           0 :                                         zend_shared_alloc_register_xlat_entry(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT(ce));
     549           0 :                                         zend_string_release(ZEND_CE_DOC_COMMENT(ce));
     550             :                                 }
     551           0 :                                 ZEND_CE_DOC_COMMENT(ce) = NULL;
     552             :                         }
     553             :                 }
     554           1 :                 zend_hash_persist(&ce->properties_info, zend_persist_property_info TSRMLS_CC);
     555           1 :                 if (ce->num_interfaces && ce->interfaces) {
     556           0 :                         efree(ce->interfaces);
     557             :                 }
     558           1 :                 ce->interfaces = NULL; /* will be filled in on fetch */
     559             : 
     560           1 :                 if (ce->num_traits && ce->traits) {
     561           0 :                         efree(ce->traits);
     562             :                 }
     563           1 :                 ce->traits = NULL;
     564             : 
     565           1 :                 if (ce->trait_aliases) {
     566           0 :                         int i = 0;
     567           0 :                         while (ce->trait_aliases[i]) {
     568           0 :                                 if (ce->trait_aliases[i]->trait_method) {
     569           0 :                                         if (ce->trait_aliases[i]->trait_method->method_name) {
     570           0 :                                                 zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->method_name);
     571             :                                         }
     572           0 :                                         if (ce->trait_aliases[i]->trait_method->class_name) {
     573           0 :                                                 zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->class_name);
     574             :                                         }
     575           0 :                                         ce->trait_aliases[i]->trait_method->ce = NULL;
     576           0 :                                         zend_accel_store(ce->trait_aliases[i]->trait_method,
     577             :                                                 sizeof(zend_trait_method_reference));
     578             :                                 }
     579             : 
     580           0 :                                 if (ce->trait_aliases[i]->alias) {
     581           0 :                                         zend_accel_store_interned_string(ce->trait_aliases[i]->alias);
     582             :                                 }
     583             : 
     584           0 :                                 zend_accel_store(ce->trait_aliases[i], sizeof(zend_trait_alias));
     585           0 :                                 i++;
     586             :                         }
     587             : 
     588           0 :                         zend_accel_store(ce->trait_aliases, sizeof(zend_trait_alias*) * (i + 1));
     589             :                 }
     590             : 
     591           1 :                 if (ce->trait_precedences) {
     592           0 :                         int i = 0;
     593             : 
     594           0 :                         while (ce->trait_precedences[i]) {
     595           0 :                                 zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->method_name);
     596           0 :                                 zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->class_name);
     597           0 :                                 ce->trait_precedences[i]->trait_method->ce = NULL;
     598           0 :                                 zend_accel_store(ce->trait_precedences[i]->trait_method,
     599             :                                         sizeof(zend_trait_method_reference));
     600             : 
     601           0 :                                 if (ce->trait_precedences[i]->exclude_from_classes) {
     602           0 :                                         int j = 0;
     603             : 
     604           0 :                                         while (ce->trait_precedences[i]->exclude_from_classes[j].class_name) {
     605           0 :                                                 zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_from_classes[j].class_name);
     606           0 :                                                 j++;
     607             :                                         }
     608           0 :                                         zend_accel_store(ce->trait_precedences[i]->exclude_from_classes,
     609             :                                                 sizeof(zend_class_entry*) * (j + 1));
     610             :                                 }
     611             : 
     612           0 :                                 zend_accel_store(ce->trait_precedences[i], sizeof(zend_trait_precedence));
     613           0 :                                 i++;
     614             :                         }
     615           0 :                         zend_accel_store(
     616             :                                 ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1));
     617             :                 }
     618             :         }
     619           1 : }
     620             : 
     621           2 : static int zend_update_property_info_ce(zval *zv TSRMLS_DC)
     622             : {
     623           2 :         zend_property_info *prop = Z_PTR_P(zv);
     624             : 
     625           2 :         prop->ce = zend_shared_alloc_get_xlat_entry(prop->ce);
     626           2 :         return 0;
     627             : }
     628             : 
     629           1 : static int zend_update_parent_ce(zval *zv TSRMLS_DC)
     630             : {
     631           1 :         zend_class_entry *ce = Z_PTR_P(zv);
     632             : 
     633           1 :         if (ce->parent) {
     634           0 :                 ce->parent = zend_shared_alloc_get_xlat_entry(ce->parent);
     635             :                 /* We use refcount to show if the class is used as a parent */
     636           0 :                 ce->parent->refcount++;
     637             :         }
     638             : 
     639             :         /* update methods */
     640           1 :         if (ce->constructor) {
     641           0 :                 ce->constructor = zend_shared_alloc_get_xlat_entry(ce->constructor);
     642             :                 /* we use refcount to show that op_array is referenced from several places */
     643           0 :                 ce->constructor->op_array.refcount++;
     644             :         }
     645           1 :         if (ce->destructor) {
     646           0 :                 ce->destructor = zend_shared_alloc_get_xlat_entry(ce->destructor);
     647           0 :                 ce->destructor->op_array.refcount++;
     648             :         }
     649           1 :         if (ce->clone) {
     650           0 :                 ce->clone = zend_shared_alloc_get_xlat_entry(ce->clone);
     651           0 :                 ce->clone->op_array.refcount++;
     652             :         }
     653           1 :         if (ce->__get) {
     654           0 :                 ce->__get = zend_shared_alloc_get_xlat_entry(ce->__get);
     655           0 :                 ce->__get->op_array.refcount++;
     656             :         }
     657           1 :         if (ce->__set) {
     658           0 :                 ce->__set = zend_shared_alloc_get_xlat_entry(ce->__set);
     659           0 :                 ce->__set->op_array.refcount++;
     660             :         }
     661           1 :         if (ce->__call) {
     662           0 :                 ce->__call = zend_shared_alloc_get_xlat_entry(ce->__call);
     663           0 :                 ce->__call->op_array.refcount++;
     664             :         }
     665           1 :         if (ce->serialize_func) {
     666           0 :                 ce->serialize_func = zend_shared_alloc_get_xlat_entry(ce->serialize_func);
     667           0 :                 ce->serialize_func->op_array.refcount++;
     668             :         }
     669           1 :         if (ce->unserialize_func) {
     670           0 :                 ce->unserialize_func = zend_shared_alloc_get_xlat_entry(ce->unserialize_func);
     671           0 :                 ce->unserialize_func->op_array.refcount++;
     672             :         }
     673           1 :         if (ce->__isset) {
     674           0 :                 ce->__isset = zend_shared_alloc_get_xlat_entry(ce->__isset);
     675           0 :                 ce->__isset->op_array.refcount++;
     676             :         }
     677           1 :         if (ce->__unset) {
     678           0 :                 ce->__unset = zend_shared_alloc_get_xlat_entry(ce->__unset);
     679           0 :                 ce->__unset->op_array.refcount++;
     680             :         }
     681           1 :         if (ce->__tostring) {
     682           0 :                 ce->__tostring = zend_shared_alloc_get_xlat_entry(ce->__tostring);
     683           0 :                 ce->__tostring->op_array.refcount++;
     684             :         }
     685           1 :         if (ce->__callstatic) {
     686           0 :                 ce->__callstatic = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
     687           0 :                 ce->__callstatic->op_array.refcount++;
     688             :         }
     689           1 :         if (ce->__debugInfo) {
     690           0 :                 ce->__debugInfo = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
     691           0 :                 ce->__debugInfo->op_array.refcount++;
     692             :         }
     693           1 :         zend_hash_apply(&ce->properties_info, (apply_func_t) zend_update_property_info_ce TSRMLS_CC);
     694           1 :         return 0;
     695             : }
     696             : 
     697         422 : static void zend_accel_persist_class_table(HashTable *class_table TSRMLS_DC)
     698             : {
     699         422 :     zend_hash_persist(class_table, zend_persist_class_entry TSRMLS_CC);
     700         422 :         zend_hash_apply(class_table, (apply_func_t) zend_update_parent_ce TSRMLS_CC);
     701         422 : }
     702             : 
     703         422 : zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length TSRMLS_DC)
     704             : {
     705         422 :         zend_shared_alloc_clear_xlat_table();
     706         422 :         zend_hash_persist(&script->function_table, zend_persist_op_array TSRMLS_CC);
     707         422 :         zend_accel_persist_class_table(&script->class_table TSRMLS_CC);
     708         422 :         zend_persist_op_array_ex(&script->main_op_array, script TSRMLS_CC);
     709         422 :         *key = zend_accel_memdup(*key, key_length + 1);
     710        1266 :         zend_accel_store_string(script->full_path);
     711         422 :         zend_accel_store(script, sizeof(zend_persistent_script));
     712             : 
     713         422 :         return script;
     714             : }
     715             : 
     716         422 : int zend_accel_script_persistable(zend_persistent_script *script)
     717             : {
     718         422 :         return 1;
     719             : }

Generated by: LCOV version 1.10

Generated at Sat, 27 Sep 2014 16:43:13 +0000 (3 days ago)

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