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: 194 376 51.6 %
Date: 2015-04-14 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         958 : static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement)
      73             : {
      74             :         uint idx;
      75             :         Bucket *p;
      76             : 
      77         958 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
      78         865 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
      79         865 :                 return;
      80             :         }
      81          93 :         if (ht->u.flags & HASH_FLAG_PACKED) {
      82          12 :                 zend_accel_store(ht->arData, sizeof(Bucket) * ht->nNumUsed);
      83          12 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
      84             :         } else {
      85          81 :                 Bucket *d = (Bucket*)ZCG(mem);
      86          81 :                 uint32_t *h = (uint32_t*)(d + ht->nNumUsed);
      87             : 
      88          81 :                 ZCG(mem) = (void*)(h + ht->nTableSize);
      89          81 :                 memcpy(d, ht->arData, sizeof(Bucket) * ht->nNumUsed);
      90          81 :                 memcpy(h, ht->arHash, sizeof(uint32_t) * ht->nTableSize);
      91          81 :                 efree(ht->arData);
      92          81 :                 ht->arData = d;
      93          81 :                 ht->arHash = h;
      94             :         }
      95         278 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
      96         185 :                 p = ht->arData + idx;
      97         370 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
      98             : 
      99             :                 /* persist bucket and key */
     100         178 :                 if (p->key) {
     101         141 :                         zend_accel_store_interned_string(p->key);
     102             :                 }
     103             : 
     104             :                 /* persist the data itself */
     105         178 :                 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        3143 : static void zend_persist_zval(zval *z)
     179             : {
     180             :         zend_uchar flags;
     181             :         void *new_ptr;
     182             : 
     183        3143 :         switch (Z_TYPE_P(z)) {
     184             :                 case IS_STRING:
     185             :                 case IS_CONSTANT:
     186        2427 :                         flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
     187        2427 :                         zend_accel_store_interned_string(Z_STR_P(z));
     188        2427 :                         Z_GC_FLAGS_P(z) |= flags;
     189        2427 :                         Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
     190        2427 :                         break;
     191             :                 case IS_ARRAY:
     192          74 :                         new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
     193          74 :                         if (new_ptr) {
     194           0 :                                 Z_ARR_P(z) = new_ptr;
     195           0 :                                 Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
     196             :                         } else {
     197          74 :                                 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          74 :                                         GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
     202          74 :                                         zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
     203          74 :                                         zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
     204             :                                         /* make immutable array */
     205          74 :                                         Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
     206          74 :                                         GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
     207          74 :                                         Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     208             :                                 }
     209             :                         }
     210          74 :                         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        3143 : }
     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         458 : static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script)
     287             : {
     288         458 :         int already_stored = 0;
     289             :         zend_op *persist_ptr;
     290         458 :         zval *orig_literals = NULL;
     291             : 
     292         458 :         if (op_array->type != ZEND_USER_FUNCTION) {
     293           0 :                 return;
     294             :         }
     295             : 
     296         458 :         if (--(*op_array->refcount) == 0) {
     297         458 :                 efree(op_array->refcount);
     298             :         }
     299         458 :         op_array->refcount = NULL;
     300             : 
     301         458 :         if (main_persistent_script) {
     302         425 :                 zend_execute_data *orig_execute_data = EG(current_execute_data);
     303             :                 zend_execute_data fake_execute_data;
     304             :                 zval *offset;
     305             : 
     306         425 :                 memset(&fake_execute_data, 0, sizeof(fake_execute_data));
     307         425 :                 fake_execute_data.func = (zend_function*)op_array;
     308         425 :                 EG(current_execute_data) = &fake_execute_data;
     309         425 :                 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         425 :                 EG(current_execute_data) = orig_execute_data;
     313             :         }
     314             : 
     315         458 :         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         458 :         if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) {
     321           0 :                 already_stored = 1;
     322             :         }
     323             : 
     324         458 :         if (op_array->literals) {
     325         458 :                 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         458 :                         zval *p = zend_accel_memdup(op_array->literals, sizeof(zval) * op_array->last_literal);
     331         458 :                         zval *end = p + op_array->last_literal;
     332         458 :                         orig_literals = op_array->literals;
     333         458 :                         op_array->literals = p;
     334        3921 :                         while (p < end) {
     335        3005 :                                 zend_persist_zval(p);
     336        3005 :                                 p++;
     337             :                         }
     338         458 :                         efree(orig_literals);
     339             :                 }
     340             :         }
     341             : 
     342         458 :         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         458 :                 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_R:
     382             :                                         case ZEND_FE_RESET_RW:
     383             :                                         case ZEND_FE_FETCH_R:
     384             :                                         case ZEND_FE_FETCH_RW:
     385             :                                                 ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes];
     386             :                                                 break;
     387             :                                 }
     388             :                         }
     389             : # endif
     390             :                 }
     391             : #endif
     392             : 
     393         458 :                 efree(op_array->opcodes);
     394         458 :                 op_array->opcodes = new_opcodes;
     395             : 
     396         458 :                 if (op_array->run_time_cache) {
     397           0 :                         efree(op_array->run_time_cache);
     398           0 :                         op_array->run_time_cache = NULL;
     399             :                 }
     400             :         }
     401             : 
     402         458 :         if (op_array->function_name && !IS_ACCEL_INTERNED(op_array->function_name)) {
     403             :                 zend_string *new_name;
     404           0 :                 if (already_stored) {
     405           0 :                         new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name);
     406             :                         ZEND_ASSERT(new_name != NULL);
     407           0 :                         op_array->function_name = new_name;
     408             :                 } else {
     409           0 :                         zend_accel_store_string(op_array->function_name);
     410             :                 }
     411             :         }
     412             : 
     413         458 :         if (op_array->filename) {
     414             :                 /* do not free! PHP has centralized filename storage, compiler will free it */
     415         916 :                 zend_accel_memdup_string(op_array->filename);
     416             :         }
     417             : 
     418         458 :         if (op_array->arg_info) {
     419          29 :                 zend_arg_info *arg_info = op_array->arg_info;
     420          29 :                 uint32_t num_args = op_array->num_args;
     421             : 
     422          29 :                 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
     423           4 :                         arg_info--;
     424           4 :                         num_args++;
     425             :                 }
     426          29 :                 if (already_stored) {
     427           0 :                         arg_info = zend_shared_alloc_get_xlat_entry(arg_info);
     428             :                         ZEND_ASSERT(arg_info != NULL);
     429             :                 } else {
     430             :                         uint32_t i;
     431             : 
     432          29 :                         if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
     433           0 :                                 num_args++;
     434             :                         }
     435          29 :                         zend_accel_store(arg_info, sizeof(zend_arg_info) * num_args);
     436          63 :                         for (i = 0; i < num_args; i++) {
     437          34 :                                 if (arg_info[i].name) {
     438          30 :                                         zend_accel_store_interned_string(arg_info[i].name);
     439             :                                 }
     440          34 :                                 if (arg_info[i].class_name) {
     441           4 :                                         zend_accel_store_interned_string(arg_info[i].class_name);
     442             :                                 }
     443             :                         }
     444             :                 }
     445          29 :                 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
     446           4 :                         arg_info++;
     447             :                 }
     448          29 :                 op_array->arg_info = arg_info;
     449             :         }
     450             : 
     451         458 :         if (op_array->brk_cont_array) {
     452          17 :                 zend_accel_store(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont);
     453             :         }
     454             : 
     455         458 :         if (op_array->scope) {
     456           9 :                 op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
     457             :         }
     458             : 
     459         458 :         if (op_array->doc_comment) {
     460           0 :                 if (ZCG(accel_directives).save_comments) {
     461           0 :                         if (already_stored) {
     462           0 :                                 op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment);
     463             :                                 ZEND_ASSERT(op_array->doc_comment != NULL);
     464             :                         } else {
     465           0 :                                 zend_accel_store_string(op_array->doc_comment);
     466             :                         }
     467             :                 } else {
     468           0 :                         if (!already_stored) {
     469           0 :                                 zend_string_release(op_array->doc_comment);
     470             :                         }
     471           0 :                         op_array->doc_comment = NULL;
     472             :                 }
     473             :         }
     474             : 
     475         458 :         if (op_array->try_catch_array) {
     476           8 :                 zend_accel_store(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
     477             :         }
     478             : 
     479         458 :         if (op_array->vars) {
     480          71 :                 if (already_stored) {
     481           0 :                         persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars);
     482             :                         ZEND_ASSERT(persist_ptr != NULL);
     483           0 :                         op_array->vars = (zend_string**)persist_ptr;
     484             :                 } else {
     485             :                         int i;
     486          71 :                         zend_accel_store(op_array->vars, sizeof(zend_string*) * op_array->last_var);
     487         239 :                         for (i = 0; i < op_array->last_var; i++) {
     488         168 :                                 zend_accel_store_interned_string(op_array->vars[i]);
     489             :                         }
     490             :                 }
     491             :         }
     492             : 
     493             :         /* "prototype" may be undefined if "scope" isn't set */
     494         460 :         if (op_array->scope && op_array->prototype) {
     495           2 :                 if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) {
     496           2 :                         op_array->prototype = (union _zend_function*)persist_ptr;
     497             :                         /* we use refcount to show that op_array is referenced from several places */
     498           2 :                         op_array->prototype->op_array.refcount++;
     499             :                 }
     500             :         } else {
     501         456 :                 op_array->prototype = NULL;
     502             :         }
     503             : }
     504             : 
     505          33 : static void zend_persist_op_array(zval *zv)
     506             : {
     507          33 :         memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_op_array));
     508          33 :         zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     509          33 :         Z_PTR_P(zv) = ZCG(arena_mem);
     510          33 :         ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_op_array)));
     511          33 :         zend_persist_op_array_ex(Z_PTR_P(zv), NULL);
     512          33 : }
     513             : 
     514           2 : static void zend_persist_property_info(zval *zv)
     515             : {
     516             :         zend_property_info *prop;
     517             : 
     518           2 :         memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_property_info));
     519           2 :         zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     520           2 :         prop = Z_PTR_P(zv) = ZCG(arena_mem);
     521           2 :         ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_property_info)));
     522           2 :         zend_accel_store_interned_string(prop->name);
     523           2 :         if (prop->doc_comment) {
     524           0 :                 if (ZCG(accel_directives).save_comments) {
     525           0 :                         zend_accel_store_string(prop->doc_comment);
     526             :                 } else {
     527           0 :                         if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) {
     528           0 :                                 zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment);
     529             :                         }
     530           0 :                         zend_string_release(prop->doc_comment);
     531           0 :                         prop->doc_comment = NULL;
     532             :                 }
     533             :         }
     534           2 : }
     535             : 
     536           7 : static void zend_persist_class_entry(zval *zv)
     537             : {
     538           7 :         zend_class_entry *ce = Z_PTR_P(zv);
     539             : 
     540           7 :         if (ce->type == ZEND_USER_CLASS) {
     541           7 :                 memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_class_entry));
     542           7 :                 zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     543           7 :                 ce = Z_PTR_P(zv) = ZCG(arena_mem);
     544           7 :                 ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_class_entry)));
     545           7 :                 zend_accel_store_interned_string(ce->name);
     546           7 :                 zend_hash_persist(&ce->function_table, zend_persist_op_array);
     547           7 :                 if (ce->default_properties_table) {
     548             :                     int i;
     549             : 
     550           0 :                         zend_accel_store(ce->default_properties_table, sizeof(zval) * ce->default_properties_count);
     551           0 :                         for (i = 0; i < ce->default_properties_count; i++) {
     552           0 :                                 zend_persist_zval(&ce->default_properties_table[i]);
     553             :                         }
     554             :                 }
     555           7 :                 if (ce->default_static_members_table) {
     556             :                     int i;
     557             : 
     558           1 :                         zend_accel_store(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count);
     559           3 :                         for (i = 0; i < ce->default_static_members_count; i++) {
     560           2 :                                 zend_persist_zval(&ce->default_static_members_table[i]);
     561             :                         }
     562             :                 }
     563           7 :                 ce->static_members_table = NULL;
     564             : 
     565           7 :                 zend_hash_persist(&ce->constants_table, zend_persist_zval);
     566             : 
     567           7 :                 if (ZEND_CE_FILENAME(ce)) {
     568             :                         /* do not free! PHP has centralized filename storage, compiler will free it */
     569          14 :                         zend_accel_memdup_string(ZEND_CE_FILENAME(ce));
     570             :                 }
     571           7 :                 if (ZEND_CE_DOC_COMMENT(ce)) {
     572           0 :                         if (ZCG(accel_directives).save_comments) {
     573           0 :                                 zend_accel_store_string(ZEND_CE_DOC_COMMENT(ce));
     574             :                         } else {
     575           0 :                                 if (!zend_shared_alloc_get_xlat_entry(ZEND_CE_DOC_COMMENT(ce))) {
     576           0 :                                         zend_shared_alloc_register_xlat_entry(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT(ce));
     577           0 :                                         zend_string_release(ZEND_CE_DOC_COMMENT(ce));
     578             :                                 }
     579           0 :                                 ZEND_CE_DOC_COMMENT(ce) = NULL;
     580             :                         }
     581             :                 }
     582           7 :                 zend_hash_persist(&ce->properties_info, zend_persist_property_info);
     583           7 :                 if (ce->num_interfaces && ce->interfaces) {
     584           0 :                         efree(ce->interfaces);
     585             :                 }
     586           7 :                 ce->interfaces = NULL; /* will be filled in on fetch */
     587             : 
     588           7 :                 if (ce->num_traits && ce->traits) {
     589           0 :                         efree(ce->traits);
     590             :                 }
     591           7 :                 ce->traits = NULL;
     592             : 
     593           7 :                 if (ce->trait_aliases) {
     594           0 :                         int i = 0;
     595           0 :                         while (ce->trait_aliases[i]) {
     596           0 :                                 if (ce->trait_aliases[i]->trait_method) {
     597           0 :                                         if (ce->trait_aliases[i]->trait_method->method_name) {
     598           0 :                                                 zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->method_name);
     599             :                                         }
     600           0 :                                         if (ce->trait_aliases[i]->trait_method->class_name) {
     601           0 :                                                 zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->class_name);
     602             :                                         }
     603           0 :                                         ce->trait_aliases[i]->trait_method->ce = NULL;
     604           0 :                                         zend_accel_store(ce->trait_aliases[i]->trait_method,
     605             :                                                 sizeof(zend_trait_method_reference));
     606             :                                 }
     607             : 
     608           0 :                                 if (ce->trait_aliases[i]->alias) {
     609           0 :                                         zend_accel_store_interned_string(ce->trait_aliases[i]->alias);
     610             :                                 }
     611             : 
     612           0 :                                 zend_accel_store(ce->trait_aliases[i], sizeof(zend_trait_alias));
     613           0 :                                 i++;
     614             :                         }
     615             : 
     616           0 :                         zend_accel_store(ce->trait_aliases, sizeof(zend_trait_alias*) * (i + 1));
     617             :                 }
     618             : 
     619           7 :                 if (ce->trait_precedences) {
     620           0 :                         int i = 0;
     621             : 
     622           0 :                         while (ce->trait_precedences[i]) {
     623           0 :                                 zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->method_name);
     624           0 :                                 zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->class_name);
     625           0 :                                 ce->trait_precedences[i]->trait_method->ce = NULL;
     626           0 :                                 zend_accel_store(ce->trait_precedences[i]->trait_method,
     627             :                                         sizeof(zend_trait_method_reference));
     628             : 
     629           0 :                                 if (ce->trait_precedences[i]->exclude_from_classes) {
     630           0 :                                         int j = 0;
     631             : 
     632           0 :                                         while (ce->trait_precedences[i]->exclude_from_classes[j].class_name) {
     633           0 :                                                 zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_from_classes[j].class_name);
     634           0 :                                                 j++;
     635             :                                         }
     636           0 :                                         zend_accel_store(ce->trait_precedences[i]->exclude_from_classes,
     637             :                                                 sizeof(zend_class_entry*) * (j + 1));
     638             :                                 }
     639             : 
     640           0 :                                 zend_accel_store(ce->trait_precedences[i], sizeof(zend_trait_precedence));
     641           0 :                                 i++;
     642             :                         }
     643           0 :                         zend_accel_store(
     644             :                                 ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1));
     645             :                 }
     646             :         }
     647           7 : }
     648             : 
     649           2 : static int zend_update_property_info_ce(zval *zv)
     650             : {
     651           2 :         zend_property_info *prop = Z_PTR_P(zv);
     652             : 
     653           2 :         prop->ce = zend_shared_alloc_get_xlat_entry(prop->ce);
     654           2 :         return 0;
     655             : }
     656             : 
     657           7 : static int zend_update_parent_ce(zval *zv)
     658             : {
     659           7 :         zend_class_entry *ce = Z_PTR_P(zv);
     660             : 
     661           7 :         if (ce->parent) {
     662           3 :                 ce->parent = zend_shared_alloc_get_xlat_entry(ce->parent);
     663             :                 /* We use refcount to show if the class is used as a parent */
     664           3 :                 ce->parent->refcount++;
     665             :         }
     666             : 
     667             :         /* update methods */
     668           7 :         if (ce->constructor) {
     669           0 :                 ce->constructor = zend_shared_alloc_get_xlat_entry(ce->constructor);
     670             :                 /* we use refcount to show that op_array is referenced from several places */
     671           0 :                 ce->constructor->op_array.refcount++;
     672             :         }
     673           7 :         if (ce->destructor) {
     674           0 :                 ce->destructor = zend_shared_alloc_get_xlat_entry(ce->destructor);
     675           0 :                 ce->destructor->op_array.refcount++;
     676             :         }
     677           7 :         if (ce->clone) {
     678           0 :                 ce->clone = zend_shared_alloc_get_xlat_entry(ce->clone);
     679           0 :                 ce->clone->op_array.refcount++;
     680             :         }
     681           7 :         if (ce->__get) {
     682           0 :                 ce->__get = zend_shared_alloc_get_xlat_entry(ce->__get);
     683           0 :                 ce->__get->op_array.refcount++;
     684             :         }
     685           7 :         if (ce->__set) {
     686           0 :                 ce->__set = zend_shared_alloc_get_xlat_entry(ce->__set);
     687           0 :                 ce->__set->op_array.refcount++;
     688             :         }
     689           7 :         if (ce->__call) {
     690           0 :                 ce->__call = zend_shared_alloc_get_xlat_entry(ce->__call);
     691           0 :                 ce->__call->op_array.refcount++;
     692             :         }
     693           7 :         if (ce->serialize_func) {
     694           0 :                 ce->serialize_func = zend_shared_alloc_get_xlat_entry(ce->serialize_func);
     695           0 :                 ce->serialize_func->op_array.refcount++;
     696             :         }
     697           7 :         if (ce->unserialize_func) {
     698           0 :                 ce->unserialize_func = zend_shared_alloc_get_xlat_entry(ce->unserialize_func);
     699           0 :                 ce->unserialize_func->op_array.refcount++;
     700             :         }
     701           7 :         if (ce->__isset) {
     702           0 :                 ce->__isset = zend_shared_alloc_get_xlat_entry(ce->__isset);
     703           0 :                 ce->__isset->op_array.refcount++;
     704             :         }
     705           7 :         if (ce->__unset) {
     706           0 :                 ce->__unset = zend_shared_alloc_get_xlat_entry(ce->__unset);
     707           0 :                 ce->__unset->op_array.refcount++;
     708             :         }
     709           7 :         if (ce->__tostring) {
     710           0 :                 ce->__tostring = zend_shared_alloc_get_xlat_entry(ce->__tostring);
     711           0 :                 ce->__tostring->op_array.refcount++;
     712             :         }
     713           7 :         if (ce->__callstatic) {
     714           0 :                 ce->__callstatic = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
     715           0 :                 ce->__callstatic->op_array.refcount++;
     716             :         }
     717           7 :         if (ce->__debugInfo) {
     718           0 :                 ce->__debugInfo = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
     719           0 :                 ce->__debugInfo->op_array.refcount++;
     720             :         }
     721           7 :         zend_hash_apply(&ce->properties_info, (apply_func_t) zend_update_property_info_ce);
     722           7 :         return 0;
     723             : }
     724             : 
     725         425 : static void zend_accel_persist_class_table(HashTable *class_table)
     726             : {
     727         425 :     zend_hash_persist(class_table, zend_persist_class_entry);
     728         425 :         zend_hash_apply(class_table, (apply_func_t) zend_update_parent_ce);
     729         425 : }
     730             : 
     731         425 : zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length)
     732             : {
     733         425 :         script->mem = ZCG(mem);
     734             : 
     735         425 :         zend_shared_alloc_clear_xlat_table();
     736             : 
     737         425 :         zend_accel_store(script, sizeof(zend_persistent_script));
     738         425 :         *key = zend_accel_memdup(*key, key_length + 1);
     739        1275 :         zend_accel_store_string(script->full_path);
     740             : 
     741         425 :         script->arena_mem = ZCG(arena_mem) = ZCG(mem);
     742         425 :         ZCG(mem) = (void*)((char*)ZCG(mem) + script->arena_size);
     743             : 
     744         425 :         zend_accel_persist_class_table(&script->class_table);
     745         425 :         zend_hash_persist(&script->function_table, zend_persist_op_array);
     746         425 :         zend_persist_op_array_ex(&script->main_op_array, script);
     747             : 
     748         425 :         return script;
     749             : }
     750             : 
     751         425 : int zend_accel_script_persistable(zend_persistent_script *script)
     752             : {
     753         425 :         return 1;
     754             : }

Generated by: LCOV version 1.10

Generated at Tue, 14 Apr 2015 11:48:46 +0000 (14 days ago)

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