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: 192 380 50.5 %
Date: 2014-10-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-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_COALESCE:
     377             :                                         case ZEND_NEW:
     378             :                                         case ZEND_FE_RESET:
     379             :                                         case ZEND_FE_FETCH:
     380         197 :                                                 ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes];
     381             :                                                 break;
     382             :                                 }
     383             :                         }
     384             :                 }
     385             : 
     386         451 :                 efree(op_array->opcodes);
     387         451 :                 op_array->opcodes = new_opcodes;
     388             : 
     389         451 :                 if (op_array->run_time_cache) {
     390           0 :                         efree(op_array->run_time_cache);
     391           0 :                         op_array->run_time_cache = NULL;
     392             :                 }
     393             :         }
     394             : 
     395         451 :         if (op_array->function_name && !IS_ACCEL_INTERNED(op_array->function_name)) {
     396             :                 zend_string *new_name;
     397           0 :                 if (already_stored) {
     398           0 :                         new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name);
     399             :                         ZEND_ASSERT(new_name != NULL);
     400           0 :                         op_array->function_name = new_name;
     401             :                 } else {
     402           0 :                         zend_accel_store_string(op_array->function_name);
     403             :                 }
     404             :         }
     405             : 
     406         451 :         if (op_array->filename) {
     407             :                 /* do not free! PHP has centralized filename storage, compiler will free it */
     408         902 :                 zend_accel_memdup_string(op_array->filename);
     409             :         }
     410             : 
     411         451 :         if (op_array->arg_info) {
     412          25 :                 if (already_stored) {
     413           0 :                         zend_arg_info *new_ptr = zend_shared_alloc_get_xlat_entry(op_array->arg_info);
     414             :                         ZEND_ASSERT(new_ptr != NULL);
     415           0 :                         op_array->arg_info = new_ptr;
     416             :                 } else {
     417             :                         uint32_t i;
     418             : 
     419          25 :                         zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args);
     420          55 :                         for (i = 0; i < op_array->num_args; i++) {
     421          30 :                                 if (op_array->arg_info[i].name) {
     422             : //???                                   zend_accel_store_interned_string(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1);
     423          30 :                                         zend_accel_store(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1);
     424             :                                 }
     425          30 :                                 if (op_array->arg_info[i].class_name) {
     426             : //???                                   zend_accel_store_interned_string(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1);
     427           0 :                                         zend_accel_store(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1);
     428             :                                 }
     429             :                         }
     430             :                 }
     431             :         }
     432             : 
     433         451 :         if (op_array->brk_cont_array) {
     434           2 :                 zend_accel_store(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont);
     435             :         }
     436             : 
     437         451 :         if (op_array->scope) {
     438           5 :                 op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
     439             :         }
     440             : 
     441         451 :         if (op_array->doc_comment) {
     442           0 :                 if (ZCG(accel_directives).save_comments) {
     443           0 :                         if (already_stored) {
     444           0 :                                 op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment);
     445             :                                 ZEND_ASSERT(op_array->doc_comment != NULL);
     446             :                         } else {
     447           0 :                                 zend_accel_store_string(op_array->doc_comment);
     448             :                         }
     449             :                 } else {
     450           0 :                         if (!already_stored) {
     451           0 :                                 zend_string_release(op_array->doc_comment);
     452             :                         }
     453           0 :                         op_array->doc_comment = NULL;
     454             :                 }
     455             :         }
     456             : 
     457         451 :         if (op_array->try_catch_array) {
     458           8 :                 zend_accel_store(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
     459             :         }
     460             : 
     461         451 :         if (op_array->vars) {
     462          71 :                 if (already_stored) {
     463           0 :                         persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars);
     464             :                         ZEND_ASSERT(persist_ptr != NULL);
     465           0 :                         op_array->vars = (zend_string**)persist_ptr;
     466             :                 } else {
     467             :                         int i;
     468          71 :                         zend_accel_store(op_array->vars, sizeof(zend_string*) * op_array->last_var);
     469         239 :                         for (i = 0; i < op_array->last_var; i++) {
     470         168 :                                 zend_accel_store_interned_string(op_array->vars[i]);
     471             :                         }
     472             :                 }
     473             :         }
     474             : 
     475             :         /* "prototype" may be undefined if "scope" isn't set */
     476         451 :         if (op_array->scope && op_array->prototype) {
     477           0 :                 if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) {
     478           0 :                         op_array->prototype = (union _zend_function*)persist_ptr;
     479             :                         /* we use refcount to show that op_array is referenced from several places */
     480           0 :                         op_array->prototype->op_array.refcount++;
     481             :                 }
     482             :         } else {
     483         451 :                 op_array->prototype = NULL;
     484             :         }
     485             : }
     486             : 
     487          29 : static void zend_persist_op_array(zval *zv TSRMLS_DC)
     488             : {
     489          29 :         memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_op_array));
     490          29 :         zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     491          29 :         Z_PTR_P(zv) = ZCG(arena_mem);
     492          29 :         ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_op_array)));
     493          29 :         zend_persist_op_array_ex(Z_PTR_P(zv), NULL TSRMLS_CC);
     494          29 : }
     495             : 
     496           2 : static void zend_persist_property_info(zval *zv TSRMLS_DC)
     497             : {
     498             :         zend_property_info *prop;
     499             : 
     500           2 :         memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_property_info));
     501           2 :         zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     502           2 :         prop = Z_PTR_P(zv) = ZCG(arena_mem);
     503           2 :         ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_property_info)));
     504           2 :         zend_accel_store_interned_string(prop->name);
     505           2 :         if (prop->doc_comment) {
     506           0 :                 if (ZCG(accel_directives).save_comments) {
     507           0 :                         zend_accel_store_string(prop->doc_comment);
     508             :                 } else {
     509           0 :                         if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) {
     510           0 :                                 zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment);
     511             :                         }
     512           0 :                         zend_string_release(prop->doc_comment);
     513           0 :                         prop->doc_comment = NULL;
     514             :                 }
     515             :         }
     516           2 : }
     517             : 
     518           1 : static void zend_persist_class_entry(zval *zv TSRMLS_DC)
     519             : {
     520           1 :         zend_class_entry *ce = Z_PTR_P(zv);
     521             : 
     522           1 :         if (ce->type == ZEND_USER_CLASS) {
     523           1 :                 memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_class_entry));
     524           1 :                 zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     525           1 :                 ce = Z_PTR_P(zv) = ZCG(arena_mem);
     526           1 :                 ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_class_entry)));
     527           1 :                 zend_accel_store_interned_string(ce->name);
     528           1 :                 zend_hash_persist(&ce->function_table, zend_persist_op_array TSRMLS_CC);
     529           1 :                 if (ce->default_properties_table) {
     530             :                     int i;
     531             : 
     532           0 :                         zend_accel_store(ce->default_properties_table, sizeof(zval) * ce->default_properties_count);
     533           0 :                         for (i = 0; i < ce->default_properties_count; i++) {
     534           0 :                                 zend_persist_zval(&ce->default_properties_table[i] TSRMLS_CC);
     535             :                         }
     536             :                 }
     537           1 :                 if (ce->default_static_members_table) {
     538             :                     int i;
     539             : 
     540           1 :                         zend_accel_store(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count);
     541           3 :                         for (i = 0; i < ce->default_static_members_count; i++) {
     542           2 :                                 zend_persist_zval(&ce->default_static_members_table[i] TSRMLS_CC);
     543             :                         }
     544             :                 }
     545           1 :                 ce->static_members_table = NULL;
     546             : 
     547           1 :                 zend_hash_persist(&ce->constants_table, zend_persist_zval TSRMLS_CC);
     548             : 
     549           1 :                 if (ZEND_CE_FILENAME(ce)) {
     550             :                         /* do not free! PHP has centralized filename storage, compiler will free it */
     551           2 :                         zend_accel_memdup_string(ZEND_CE_FILENAME(ce));
     552             :                 }
     553           1 :                 if (ZEND_CE_DOC_COMMENT(ce)) {
     554           0 :                         if (ZCG(accel_directives).save_comments) {
     555           0 :                                 zend_accel_store_string(ZEND_CE_DOC_COMMENT(ce));
     556             :                         } else {
     557           0 :                                 if (!zend_shared_alloc_get_xlat_entry(ZEND_CE_DOC_COMMENT(ce))) {
     558           0 :                                         zend_shared_alloc_register_xlat_entry(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT(ce));
     559           0 :                                         zend_string_release(ZEND_CE_DOC_COMMENT(ce));
     560             :                                 }
     561           0 :                                 ZEND_CE_DOC_COMMENT(ce) = NULL;
     562             :                         }
     563             :                 }
     564           1 :                 zend_hash_persist(&ce->properties_info, zend_persist_property_info TSRMLS_CC);
     565           1 :                 if (ce->num_interfaces && ce->interfaces) {
     566           0 :                         efree(ce->interfaces);
     567             :                 }
     568           1 :                 ce->interfaces = NULL; /* will be filled in on fetch */
     569             : 
     570           1 :                 if (ce->num_traits && ce->traits) {
     571           0 :                         efree(ce->traits);
     572             :                 }
     573           1 :                 ce->traits = NULL;
     574             : 
     575           1 :                 if (ce->trait_aliases) {
     576           0 :                         int i = 0;
     577           0 :                         while (ce->trait_aliases[i]) {
     578           0 :                                 if (ce->trait_aliases[i]->trait_method) {
     579           0 :                                         if (ce->trait_aliases[i]->trait_method->method_name) {
     580           0 :                                                 zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->method_name);
     581             :                                         }
     582           0 :                                         if (ce->trait_aliases[i]->trait_method->class_name) {
     583           0 :                                                 zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->class_name);
     584             :                                         }
     585           0 :                                         ce->trait_aliases[i]->trait_method->ce = NULL;
     586           0 :                                         zend_accel_store(ce->trait_aliases[i]->trait_method,
     587             :                                                 sizeof(zend_trait_method_reference));
     588             :                                 }
     589             : 
     590           0 :                                 if (ce->trait_aliases[i]->alias) {
     591           0 :                                         zend_accel_store_interned_string(ce->trait_aliases[i]->alias);
     592             :                                 }
     593             : 
     594           0 :                                 zend_accel_store(ce->trait_aliases[i], sizeof(zend_trait_alias));
     595           0 :                                 i++;
     596             :                         }
     597             : 
     598           0 :                         zend_accel_store(ce->trait_aliases, sizeof(zend_trait_alias*) * (i + 1));
     599             :                 }
     600             : 
     601           1 :                 if (ce->trait_precedences) {
     602           0 :                         int i = 0;
     603             : 
     604           0 :                         while (ce->trait_precedences[i]) {
     605           0 :                                 zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->method_name);
     606           0 :                                 zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->class_name);
     607           0 :                                 ce->trait_precedences[i]->trait_method->ce = NULL;
     608           0 :                                 zend_accel_store(ce->trait_precedences[i]->trait_method,
     609             :                                         sizeof(zend_trait_method_reference));
     610             : 
     611           0 :                                 if (ce->trait_precedences[i]->exclude_from_classes) {
     612           0 :                                         int j = 0;
     613             : 
     614           0 :                                         while (ce->trait_precedences[i]->exclude_from_classes[j].class_name) {
     615           0 :                                                 zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_from_classes[j].class_name);
     616           0 :                                                 j++;
     617             :                                         }
     618           0 :                                         zend_accel_store(ce->trait_precedences[i]->exclude_from_classes,
     619             :                                                 sizeof(zend_class_entry*) * (j + 1));
     620             :                                 }
     621             : 
     622           0 :                                 zend_accel_store(ce->trait_precedences[i], sizeof(zend_trait_precedence));
     623           0 :                                 i++;
     624             :                         }
     625           0 :                         zend_accel_store(
     626             :                                 ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1));
     627             :                 }
     628             :         }
     629           1 : }
     630             : 
     631           2 : static int zend_update_property_info_ce(zval *zv TSRMLS_DC)
     632             : {
     633           2 :         zend_property_info *prop = Z_PTR_P(zv);
     634             : 
     635           2 :         prop->ce = zend_shared_alloc_get_xlat_entry(prop->ce);
     636           2 :         return 0;
     637             : }
     638             : 
     639           1 : static int zend_update_parent_ce(zval *zv TSRMLS_DC)
     640             : {
     641           1 :         zend_class_entry *ce = Z_PTR_P(zv);
     642             : 
     643           1 :         if (ce->parent) {
     644           0 :                 ce->parent = zend_shared_alloc_get_xlat_entry(ce->parent);
     645             :                 /* We use refcount to show if the class is used as a parent */
     646           0 :                 ce->parent->refcount++;
     647             :         }
     648             : 
     649             :         /* update methods */
     650           1 :         if (ce->constructor) {
     651           0 :                 ce->constructor = zend_shared_alloc_get_xlat_entry(ce->constructor);
     652             :                 /* we use refcount to show that op_array is referenced from several places */
     653           0 :                 ce->constructor->op_array.refcount++;
     654             :         }
     655           1 :         if (ce->destructor) {
     656           0 :                 ce->destructor = zend_shared_alloc_get_xlat_entry(ce->destructor);
     657           0 :                 ce->destructor->op_array.refcount++;
     658             :         }
     659           1 :         if (ce->clone) {
     660           0 :                 ce->clone = zend_shared_alloc_get_xlat_entry(ce->clone);
     661           0 :                 ce->clone->op_array.refcount++;
     662             :         }
     663           1 :         if (ce->__get) {
     664           0 :                 ce->__get = zend_shared_alloc_get_xlat_entry(ce->__get);
     665           0 :                 ce->__get->op_array.refcount++;
     666             :         }
     667           1 :         if (ce->__set) {
     668           0 :                 ce->__set = zend_shared_alloc_get_xlat_entry(ce->__set);
     669           0 :                 ce->__set->op_array.refcount++;
     670             :         }
     671           1 :         if (ce->__call) {
     672           0 :                 ce->__call = zend_shared_alloc_get_xlat_entry(ce->__call);
     673           0 :                 ce->__call->op_array.refcount++;
     674             :         }
     675           1 :         if (ce->serialize_func) {
     676           0 :                 ce->serialize_func = zend_shared_alloc_get_xlat_entry(ce->serialize_func);
     677           0 :                 ce->serialize_func->op_array.refcount++;
     678             :         }
     679           1 :         if (ce->unserialize_func) {
     680           0 :                 ce->unserialize_func = zend_shared_alloc_get_xlat_entry(ce->unserialize_func);
     681           0 :                 ce->unserialize_func->op_array.refcount++;
     682             :         }
     683           1 :         if (ce->__isset) {
     684           0 :                 ce->__isset = zend_shared_alloc_get_xlat_entry(ce->__isset);
     685           0 :                 ce->__isset->op_array.refcount++;
     686             :         }
     687           1 :         if (ce->__unset) {
     688           0 :                 ce->__unset = zend_shared_alloc_get_xlat_entry(ce->__unset);
     689           0 :                 ce->__unset->op_array.refcount++;
     690             :         }
     691           1 :         if (ce->__tostring) {
     692           0 :                 ce->__tostring = zend_shared_alloc_get_xlat_entry(ce->__tostring);
     693           0 :                 ce->__tostring->op_array.refcount++;
     694             :         }
     695           1 :         if (ce->__callstatic) {
     696           0 :                 ce->__callstatic = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
     697           0 :                 ce->__callstatic->op_array.refcount++;
     698             :         }
     699           1 :         if (ce->__debugInfo) {
     700           0 :                 ce->__debugInfo = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
     701           0 :                 ce->__debugInfo->op_array.refcount++;
     702             :         }
     703           1 :         zend_hash_apply(&ce->properties_info, (apply_func_t) zend_update_property_info_ce TSRMLS_CC);
     704           1 :         return 0;
     705             : }
     706             : 
     707         422 : static void zend_accel_persist_class_table(HashTable *class_table TSRMLS_DC)
     708             : {
     709         422 :     zend_hash_persist(class_table, zend_persist_class_entry TSRMLS_CC);
     710         422 :         zend_hash_apply(class_table, (apply_func_t) zend_update_parent_ce TSRMLS_CC);
     711         422 : }
     712             : 
     713         422 : zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length TSRMLS_DC)
     714             : {
     715         422 :         script->mem = ZCG(mem);
     716             : 
     717         422 :         zend_shared_alloc_clear_xlat_table();
     718             :         
     719         422 :         zend_accel_store(script, sizeof(zend_persistent_script));
     720         422 :         *key = zend_accel_memdup(*key, key_length + 1);
     721        1266 :         zend_accel_store_string(script->full_path);
     722             : 
     723         422 :         script->arena_mem = ZCG(arena_mem) = ZCG(mem);
     724         422 :         ZCG(mem) = (void*)((char*)ZCG(mem) + script->arena_size);
     725             : 
     726         422 :         zend_accel_persist_class_table(&script->class_table TSRMLS_CC);
     727         422 :         zend_hash_persist(&script->function_table, zend_persist_op_array TSRMLS_CC);
     728         422 :         zend_persist_op_array_ex(&script->main_op_array, script TSRMLS_CC);
     729             : 
     730         422 :         return script;
     731             : }
     732             : 
     733         422 : int zend_accel_script_persistable(zend_persistent_script *script)
     734             : {
     735         422 :         return 1;
     736             : }

Generated by: LCOV version 1.10

Generated at Tue, 14 Oct 2014 07:25:44 +0000 (6 days ago)

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