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: 239 427 56.0 %
Date: 2016-08-28 Functions: 11 13 84.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend OPcache                                                         |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2016 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, _ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); \
      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, _ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); \
      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             : 
      69             : static const uint32_t uninitialized_bucket[-HT_MIN_MASK] =
      70             :         {HT_INVALID_IDX, HT_INVALID_IDX};
      71             : 
      72         974 : static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement)
      73             : {
      74             :         uint32_t idx, nIndex;
      75             :         Bucket *p;
      76             : 
      77         974 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
      78         472 :                 HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
      79         472 :                 return;
      80             :         }
      81         502 :         if (ht->nNumUsed == 0) {
      82         409 :                 efree(HT_GET_DATA_ADDR(ht));
      83         409 :                 ht->nTableMask = HT_MIN_MASK;
      84         409 :                 HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
      85         409 :                 ht->u.flags &= ~HASH_FLAG_INITIALIZED;
      86         409 :                 return;
      87             :         }
      88          93 :         if (ht->u.flags & HASH_FLAG_PACKED) {
      89          12 :                 void *data = HT_GET_DATA_ADDR(ht);
      90          12 :                 zend_accel_store(data, HT_USED_SIZE(ht));
      91          12 :                 HT_SET_DATA_ADDR(ht, data);
      92          81 :         } else if (ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 2) {
      93             :                 /* compact table */
      94          77 :                 void *old_data = HT_GET_DATA_ADDR(ht);
      95          77 :                 Bucket *old_buckets = ht->arData;
      96             :                 uint32_t hash_size;
      97             : 
      98          77 :                 if (ht->nNumUsed <= HT_MIN_SIZE) {
      99          77 :                         hash_size = HT_MIN_SIZE;
     100             :                 } else {
     101           0 :                         hash_size = (uint32_t)(-(int32_t)ht->nTableMask);
     102           0 :                         while (hash_size >> 1 > ht->nNumUsed) {
     103           0 :                                 hash_size >>= 1;
     104             :                         }
     105             :                 }
     106          77 :                 ht->nTableMask = (uint32_t)(-(int32_t)hash_size);
     107             :                 ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
     108          77 :                 HT_SET_DATA_ADDR(ht, ZCG(mem));
     109          77 :                 ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE((hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket))));
     110          77 :                 HT_HASH_RESET(ht);
     111          77 :                 memcpy(ht->arData, old_buckets, ht->nNumUsed * sizeof(Bucket));
     112          77 :                 efree(old_data);
     113             : 
     114         167 :                 for (idx = 0; idx < ht->nNumUsed; idx++) {
     115          90 :                         p = ht->arData + idx;
     116         180 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
     117             : 
     118             :                         /* persist bucket and key */
     119          83 :                         if (p->key) {
     120          83 :                                 zend_accel_store_interned_string(p->key);
     121             :                         }
     122             : 
     123             :                         /* persist the data itself */
     124          83 :                         pPersistElement(&p->val);
     125             : 
     126          83 :                         nIndex = p->h | ht->nTableMask;
     127          83 :                         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     128          83 :                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
     129             :                 }
     130          77 :                 return;
     131             :         } else {
     132           4 :                 void *data = ZCG(mem);
     133           4 :                 void *old_data = HT_GET_DATA_ADDR(ht);
     134             : 
     135             :                 ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
     136           4 :                 ZCG(mem) = (void*)((char*)data + HT_USED_SIZE(ht));
     137           4 :                 memcpy(data, old_data, HT_USED_SIZE(ht));
     138           4 :                 efree(old_data);
     139           4 :                 HT_SET_DATA_ADDR(ht, data);
     140             :         }
     141             : 
     142         111 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
     143          95 :                 p = ht->arData + idx;
     144         190 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     145             : 
     146             :                 /* persist bucket and key */
     147          95 :                 if (p->key) {
     148          58 :                         zend_accel_store_interned_string(p->key);
     149             :                 }
     150             : 
     151             :                 /* persist the data itself */
     152          95 :                 pPersistElement(&p->val);
     153             :         }
     154             : }
     155             : 
     156           0 : static void zend_hash_persist_immutable(HashTable *ht)
     157             : {
     158             :         uint32_t idx, nIndex;
     159             :         Bucket *p;
     160             : 
     161           0 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
     162           0 :                 HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
     163           0 :                 return;
     164             :         }
     165           0 :         if (ht->nNumUsed == 0) {
     166           0 :                 efree(HT_GET_DATA_ADDR(ht));
     167           0 :                 ht->nTableMask = HT_MIN_MASK;
     168           0 :                 HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
     169           0 :                 ht->u.flags &= ~HASH_FLAG_INITIALIZED;
     170           0 :                 return;
     171             :         }
     172           0 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     173           0 :                 HT_SET_DATA_ADDR(ht, zend_accel_memdup(HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht)));
     174           0 :         } else if (ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 2) {
     175             :                 /* compact table */
     176           0 :                 void *old_data = HT_GET_DATA_ADDR(ht);
     177           0 :                 Bucket *old_buckets = ht->arData;
     178             :                 uint32_t hash_size;
     179             : 
     180           0 :                 if (ht->nNumUsed <= HT_MIN_SIZE) {
     181           0 :                         hash_size = HT_MIN_SIZE;
     182             :                 } else {
     183           0 :                         hash_size = (uint32_t)(-(int32_t)ht->nTableMask);
     184           0 :                         while (hash_size >> 1 > ht->nNumUsed) {
     185           0 :                                 hash_size >>= 1;
     186             :                         }
     187             :                 }
     188           0 :                 ht->nTableMask = (uint32_t)(-(int32_t)hash_size);
     189             :                 ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
     190           0 :                 HT_SET_DATA_ADDR(ht, ZCG(mem));
     191           0 :                 ZCG(mem) = (void*)((char*)ZCG(mem) + (hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket)));
     192           0 :                 HT_HASH_RESET(ht);
     193           0 :                 memcpy(ht->arData, old_buckets, ht->nNumUsed * sizeof(Bucket));
     194           0 :                 efree(old_data);
     195             : 
     196           0 :                 for (idx = 0; idx < ht->nNumUsed; idx++) {
     197           0 :                         p = ht->arData + idx;
     198           0 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
     199             : 
     200             :                         /* persist bucket and key */
     201           0 :                         if (p->key) {
     202           0 :                                 zend_accel_memdup_interned_string(p->key);
     203             :                         }
     204             : 
     205             :                         /* persist the data itself */
     206           0 :                         zend_persist_zval(&p->val);
     207             : 
     208           0 :                         nIndex = p->h | ht->nTableMask;
     209           0 :                         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     210           0 :                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
     211             :                 }
     212           0 :                 return;
     213             :         } else {
     214           0 :                 void *data = ZCG(mem);
     215             : 
     216             :                 ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
     217           0 :                 ZCG(mem) = (void*)((char*)data + HT_USED_SIZE(ht));
     218           0 :                 memcpy(data, HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht));
     219           0 :                 HT_SET_DATA_ADDR(ht, data);
     220             :         }
     221           0 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
     222           0 :                 p = ht->arData + idx;
     223           0 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     224             : 
     225             :                 /* persist bucket and key */
     226           0 :                 if (p->key) {
     227           0 :                         zend_accel_memdup_interned_string(p->key);
     228             :                 }
     229             : 
     230             :                 /* persist the data itself */
     231           0 :                 zend_persist_zval(&p->val);
     232             :         }
     233             : }
     234             : 
     235           0 : static zend_ast *zend_persist_ast(zend_ast *ast)
     236             : {
     237             :         uint32_t i;
     238             :         zend_ast *node;
     239             : 
     240           0 :         if (ast->kind == ZEND_AST_ZVAL) {
     241           0 :                 zend_ast_zval *copy = zend_accel_memdup(ast, sizeof(zend_ast_zval));
     242           0 :                 zend_persist_zval(&copy->val);
     243           0 :                 node = (zend_ast *) copy;
     244           0 :         } else if (zend_ast_is_list(ast)) {
     245           0 :                 zend_ast_list *list = zend_ast_get_list(ast);
     246           0 :                 zend_ast_list *copy = zend_accel_memdup(ast,
     247             :                         sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
     248           0 :                 for (i = 0; i < list->children; i++) {
     249           0 :                         if (copy->child[i]) {
     250           0 :                                 copy->child[i] = zend_persist_ast(copy->child[i]);
     251             :                         }
     252             :                 }
     253           0 :                 node = (zend_ast *) copy;
     254             :         } else {
     255           0 :                 uint32_t children = zend_ast_get_num_children(ast);
     256           0 :                 node = zend_accel_memdup(ast, sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children);
     257           0 :                 for (i = 0; i < children; i++) {
     258           0 :                         if (node->child[i]) {
     259           0 :                                 node->child[i] = zend_persist_ast(node->child[i]);
     260             :                         }
     261             :                 }
     262             :         }
     263             : 
     264           0 :         efree(ast);
     265           0 :         return node;
     266             : }
     267             : 
     268        3130 : static void zend_persist_zval(zval *z)
     269             : {
     270             :         zend_uchar flags;
     271             :         void *new_ptr;
     272             : 
     273        3130 :         switch (Z_TYPE_P(z)) {
     274             :                 case IS_STRING:
     275             :                 case IS_CONSTANT:
     276        2413 :                         flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
     277        2413 :                         zend_accel_store_interned_string(Z_STR_P(z));
     278        2413 :                         Z_GC_FLAGS_P(z) |= flags;
     279        2413 :                         Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
     280        2413 :                         if (Z_TYPE_P(z) == IS_CONSTANT) {
     281           0 :                                 Z_TYPE_FLAGS_P(z) |= IS_TYPE_IMMUTABLE;
     282             :                         }
     283        2413 :                         break;
     284             :                 case IS_ARRAY:
     285          74 :                         new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
     286          74 :                         if (new_ptr) {
     287           0 :                                 Z_ARR_P(z) = new_ptr;
     288           0 :                                 Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
     289             :                         } else {
     290          74 :                                 if (Z_IMMUTABLE_P(z)) {
     291           0 :                                         Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array));
     292           0 :                                         zend_hash_persist_immutable(Z_ARRVAL_P(z));
     293             :                                 } else {
     294          74 :                                         GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
     295          74 :                                         zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
     296          74 :                                         zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
     297             :                                         /* make immutable array */
     298          74 :                                         Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
     299          74 :                                         GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
     300          74 :                                         GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE;
     301          74 :                                         Z_ARRVAL_P(z)->u.flags |= HASH_FLAG_STATIC_KEYS;
     302          74 :                                         Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     303             :                                 }
     304             :                         }
     305          74 :                         break;
     306             :                 case IS_REFERENCE:
     307           0 :                         new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z));
     308           0 :                         if (new_ptr) {
     309           0 :                                 Z_REF_P(z) = new_ptr;
     310             :                         } else {
     311           0 :                                 zend_accel_store(Z_REF_P(z), sizeof(zend_reference));
     312           0 :                                 zend_persist_zval(Z_REFVAL_P(z));
     313             :                         }
     314           0 :                         break;
     315             :                 case IS_CONSTANT_AST:
     316           0 :                         new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
     317           0 :                         if (new_ptr) {
     318           0 :                                 Z_AST_P(z) = new_ptr;
     319           0 :                                 Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_IMMUTABLE;
     320             :                         } else {
     321           0 :                                 zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
     322           0 :                                 Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
     323           0 :                                 Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_IMMUTABLE;
     324           0 :                                 GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
     325             :                         }
     326             :                         break;
     327             :         }
     328        3130 : }
     329             : 
     330         466 : static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script)
     331             : {
     332         466 :         int already_stored = 0;
     333             :         zend_op *persist_ptr;
     334         466 :         zval *orig_literals = NULL;
     335             : 
     336         466 :         if (op_array->type != ZEND_USER_FUNCTION) {
     337           0 :                 return;
     338             :         }
     339             : 
     340         466 :         if (op_array->refcount && --(*op_array->refcount) == 0) {
     341         466 :                 efree(op_array->refcount);
     342             :         }
     343         466 :         op_array->refcount = NULL;
     344             : 
     345         466 :         if (main_persistent_script) {
     346         433 :                 zend_execute_data *orig_execute_data = EG(current_execute_data);
     347             :                 zend_execute_data fake_execute_data;
     348             :                 zval *offset;
     349             : 
     350         433 :                 memset(&fake_execute_data, 0, sizeof(fake_execute_data));
     351         433 :                 fake_execute_data.func = (zend_function*)op_array;
     352         433 :                 EG(current_execute_data) = &fake_execute_data;
     353         433 :                 if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
     354          95 :                         main_persistent_script->compiler_halt_offset = Z_LVAL_P(offset);
     355             :                 }
     356         433 :                 EG(current_execute_data) = orig_execute_data;
     357             :         }
     358             : 
     359         466 :         if (op_array->static_variables) {
     360          13 :                 HashTable *stored = zend_shared_alloc_get_xlat_entry(op_array->static_variables);
     361             : 
     362          13 :                 if (stored) {
     363           0 :                         op_array->static_variables = stored;
     364             :                 } else {
     365          13 :                         zend_hash_persist(op_array->static_variables, zend_persist_zval);
     366          13 :                         zend_accel_store(op_array->static_variables, sizeof(HashTable));
     367             :                         /* make immutable array */
     368          13 :                         GC_REFCOUNT(op_array->static_variables) = 2;
     369          13 :                         GC_TYPE_INFO(op_array->static_variables) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << 8);
     370          13 :                         op_array->static_variables->u.flags |= HASH_FLAG_STATIC_KEYS;
     371          13 :                         op_array->static_variables->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     372             :                 }
     373             :         }
     374             : 
     375         466 :         if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) {
     376           0 :                 already_stored = 1;
     377             :         }
     378             : 
     379         466 :         if (op_array->literals) {
     380         466 :                 if (already_stored) {
     381           0 :                         orig_literals = zend_shared_alloc_get_xlat_entry(op_array->literals);
     382             :                         ZEND_ASSERT(orig_literals != NULL);
     383           0 :                         op_array->literals = orig_literals;
     384             :                 } else {
     385         466 :                         zval *p = zend_accel_memdup(op_array->literals, sizeof(zval) * op_array->last_literal);
     386         466 :                         zval *end = p + op_array->last_literal;
     387         466 :                         orig_literals = op_array->literals;
     388         466 :                         op_array->literals = p;
     389        3924 :                         while (p < end) {
     390        2992 :                                 zend_persist_zval(p);
     391        2992 :                                 p++;
     392             :                         }
     393         466 :                         efree(orig_literals);
     394             :                 }
     395             :         }
     396             : 
     397         466 :         if (already_stored) {
     398           0 :                 persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
     399             :                 ZEND_ASSERT(persist_ptr != NULL);
     400           0 :                 op_array->opcodes = persist_ptr;
     401             :         } else {
     402         466 :                 zend_op *new_opcodes = zend_accel_memdup(op_array->opcodes, sizeof(zend_op) * op_array->last);
     403             : #if ZEND_USE_ABS_CONST_ADDR || ZEND_USE_ABS_JMP_ADDR
     404             :                 zend_op *opline = new_opcodes;
     405             :                 zend_op *end = new_opcodes + op_array->last;
     406             :                 int offset = 0;
     407             : 
     408             :                 for (; opline < end ; opline++, offset++) {
     409             : # if ZEND_USE_ABS_CONST_ADDR
     410             :                         if (opline->op1_type == IS_CONST) {
     411             :                                 opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals));
     412             :                         }
     413             :                         if (opline->op2_type == IS_CONST) {
     414             :                                 opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals));
     415             :                         }
     416             : # endif
     417             : # if ZEND_USE_ABS_JMP_ADDR
     418             :                         if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
     419             :                                 /* fix jumps to point to new array */
     420             :                                 switch (opline->opcode) {
     421             :                                         case ZEND_JMP:
     422             :                                         case ZEND_FAST_CALL:
     423             :                                                 opline->op1.jmp_addr = &new_opcodes[opline->op1.jmp_addr - op_array->opcodes];
     424             :                                                 break;
     425             :                                         case ZEND_JMPZNZ:
     426             :                                                 /* relative extended_value don't have to be changed */
     427             :                                                 /* break omitted intentionally */
     428             :                                         case ZEND_JMPZ:
     429             :                                         case ZEND_JMPNZ:
     430             :                                         case ZEND_JMPZ_EX:
     431             :                                         case ZEND_JMPNZ_EX:
     432             :                                         case ZEND_JMP_SET:
     433             :                                         case ZEND_COALESCE:
     434             :                                         case ZEND_FE_RESET_R:
     435             :                                         case ZEND_FE_RESET_RW:
     436             :                                         case ZEND_ASSERT_CHECK:
     437             :                                                 opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes];
     438             :                                                 break;
     439             :                                         case ZEND_DECLARE_ANON_CLASS:
     440             :                                         case ZEND_DECLARE_ANON_INHERITED_CLASS:
     441             :                                         case ZEND_FE_FETCH_R:
     442             :                                         case ZEND_FE_FETCH_RW:
     443             :                                                 /* relative extended_value don't have to be changed */
     444             :                                                 break;
     445             :                                 }
     446             :                         }
     447             : # endif
     448             :                 }
     449             : #endif
     450             : 
     451         466 :                 efree(op_array->opcodes);
     452         466 :                 op_array->opcodes = new_opcodes;
     453             : 
     454         466 :                 if (op_array->run_time_cache) {
     455           0 :                         efree(op_array->run_time_cache);
     456           0 :                         op_array->run_time_cache = NULL;
     457             :                 }
     458             :         }
     459             : 
     460         466 :         if (op_array->function_name && !IS_ACCEL_INTERNED(op_array->function_name)) {
     461             :                 zend_string *new_name;
     462           0 :                 if (already_stored) {
     463           0 :                         new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name);
     464             :                         ZEND_ASSERT(new_name != NULL);
     465           0 :                         op_array->function_name = new_name;
     466             :                 } else {
     467           0 :                         zend_accel_store_string(op_array->function_name);
     468             :                 }
     469             :         }
     470             : 
     471         466 :         if (op_array->filename) {
     472             :                 /* do not free! PHP has centralized filename storage, compiler will free it */
     473         932 :                 zend_accel_memdup_string(op_array->filename);
     474             :         }
     475             : 
     476         466 :         if (op_array->arg_info) {
     477          29 :                 zend_arg_info *arg_info = op_array->arg_info;
     478          29 :                 uint32_t num_args = op_array->num_args;
     479             : 
     480          29 :                 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
     481           4 :                         arg_info--;
     482           4 :                         num_args++;
     483             :                 }
     484          29 :                 if (already_stored) {
     485           0 :                         arg_info = zend_shared_alloc_get_xlat_entry(arg_info);
     486             :                         ZEND_ASSERT(arg_info != NULL);
     487             :                 } else {
     488             :                         uint32_t i;
     489             : 
     490          29 :                         if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
     491           0 :                                 num_args++;
     492             :                         }
     493          29 :                         zend_accel_store(arg_info, sizeof(zend_arg_info) * num_args);
     494          63 :                         for (i = 0; i < num_args; i++) {
     495          34 :                                 if (arg_info[i].name) {
     496          30 :                                         zend_accel_store_interned_string(arg_info[i].name);
     497             :                                 }
     498          34 :                                 if (arg_info[i].class_name) {
     499           4 :                                         zend_accel_store_interned_string(arg_info[i].class_name);
     500             :                                 }
     501             :                         }
     502             :                 }
     503          29 :                 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
     504           4 :                         arg_info++;
     505             :                 }
     506          29 :                 op_array->arg_info = arg_info;
     507             :         }
     508             : 
     509         466 :         if (op_array->live_range) {
     510          72 :                 zend_accel_store(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
     511             :         }
     512             : 
     513         466 :         if (op_array->scope) {
     514           9 :                 op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
     515             :         }
     516             : 
     517         466 :         if (op_array->doc_comment) {
     518           0 :                 if (ZCG(accel_directives).save_comments) {
     519           0 :                         if (already_stored) {
     520           0 :                                 op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment);
     521             :                                 ZEND_ASSERT(op_array->doc_comment != NULL);
     522             :                         } else {
     523           0 :                                 zend_accel_store_string(op_array->doc_comment);
     524             :                         }
     525             :                 } else {
     526           0 :                         if (!already_stored) {
     527           0 :                                 zend_string_release(op_array->doc_comment);
     528             :                         }
     529           0 :                         op_array->doc_comment = NULL;
     530             :                 }
     531             :         }
     532             : 
     533         466 :         if (op_array->try_catch_array) {
     534           8 :                 zend_accel_store(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
     535             :         }
     536             : 
     537         466 :         if (op_array->vars) {
     538          73 :                 if (already_stored) {
     539           0 :                         persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars);
     540             :                         ZEND_ASSERT(persist_ptr != NULL);
     541           0 :                         op_array->vars = (zend_string**)persist_ptr;
     542             :                 } else {
     543             :                         int i;
     544          73 :                         zend_accel_store(op_array->vars, sizeof(zend_string*) * op_array->last_var);
     545         245 :                         for (i = 0; i < op_array->last_var; i++) {
     546         172 :                                 zend_accel_store_interned_string(op_array->vars[i]);
     547             :                         }
     548             :                 }
     549             :         }
     550             : 
     551             :         /* "prototype" may be undefined if "scope" isn't set */
     552         468 :         if (op_array->scope && op_array->prototype) {
     553           2 :                 if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) {
     554           2 :                         op_array->prototype = (union _zend_function*)persist_ptr;
     555             :                 }
     556             :         } else {
     557         464 :                 op_array->prototype = NULL;
     558             :         }
     559             : 
     560         466 :         ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist(op_array, ZCG(mem))));
     561             : }
     562             : 
     563          33 : static void zend_persist_op_array(zval *zv)
     564             : {
     565          33 :         zend_op_array *op_array = Z_PTR_P(zv);
     566          33 :         zend_op_array *old_op_array = zend_shared_alloc_get_xlat_entry(op_array);
     567          33 :         if (old_op_array) {
     568           0 :                 Z_PTR_P(zv) = old_op_array;
     569           0 :                 if (op_array->refcount && --(*op_array->refcount) == 0) {
     570           0 :                         efree(op_array->refcount);
     571             :                 }
     572           0 :                 return;
     573             :         }
     574          33 :         memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_op_array));
     575          33 :         zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     576          33 :         Z_PTR_P(zv) = ZCG(arena_mem);
     577          33 :         ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_op_array)));
     578          33 :         zend_persist_op_array_ex(Z_PTR_P(zv), NULL);
     579             : }
     580             : 
     581           2 : static void zend_persist_property_info(zval *zv)
     582             : {
     583           2 :         zend_property_info *prop = zend_shared_alloc_get_xlat_entry(Z_PTR_P(zv));
     584             : 
     585           2 :         if (prop) {
     586           0 :                 Z_PTR_P(zv) = prop;
     587           0 :                 return;
     588             :         }
     589           2 :         memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_property_info));
     590           2 :         zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     591           2 :         prop = Z_PTR_P(zv) = ZCG(arena_mem);
     592           2 :         ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_property_info)));
     593           2 :         prop->ce = zend_shared_alloc_get_xlat_entry(prop->ce);
     594           2 :         zend_accel_store_interned_string(prop->name);
     595           2 :         if (prop->doc_comment) {
     596           0 :                 if (ZCG(accel_directives).save_comments) {
     597           0 :                         zend_accel_store_string(prop->doc_comment);
     598             :                 } else {
     599           0 :                         if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) {
     600           0 :                                 zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment);
     601             :                         }
     602           0 :                         zend_string_release(prop->doc_comment);
     603           0 :                         prop->doc_comment = NULL;
     604             :                 }
     605             :         }
     606             : }
     607             : 
     608           5 : static void zend_persist_class_constant(zval *zv)
     609             : {
     610           5 :         zend_class_constant *c = zend_shared_alloc_get_xlat_entry(Z_PTR_P(zv));
     611             : 
     612           5 :         if (c) {
     613           0 :                 Z_PTR_P(zv) = c;
     614           0 :                 return;
     615             :         }
     616           5 :         memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_class_constant));
     617           5 :         zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     618           5 :         c = Z_PTR_P(zv) = ZCG(arena_mem);
     619           5 :         ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_class_constant)));
     620           5 :         zend_persist_zval(&c->value);
     621           5 :         c->ce = zend_shared_alloc_get_xlat_entry(c->ce);
     622           5 :         if (c->doc_comment) {
     623           0 :                 if (ZCG(accel_directives).save_comments) {
     624           0 :                         zend_string *doc_comment = zend_shared_alloc_get_xlat_entry(c->doc_comment);
     625           0 :                         if (doc_comment) {
     626           0 :                                 c->doc_comment = doc_comment;
     627             :                         } else {
     628           0 :                                 zend_accel_store_string(c->doc_comment);
     629             :                         }
     630             :                 } else {
     631           0 :                         zend_string *doc_comment = zend_shared_alloc_get_xlat_entry(c->doc_comment);
     632           0 :                         if (!doc_comment) {
     633           0 :                                 zend_shared_alloc_register_xlat_entry(c->doc_comment, c->doc_comment);
     634           0 :                                 zend_string_release(c->doc_comment);
     635             :                         }
     636           0 :                         c->doc_comment = NULL;
     637             :                 }
     638             :         }
     639             : }
     640             : 
     641           7 : static void zend_persist_class_entry(zval *zv)
     642             : {
     643           7 :         zend_class_entry *ce = Z_PTR_P(zv);
     644             : 
     645           7 :         if (ce->type == ZEND_USER_CLASS) {
     646           7 :                 memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_class_entry));
     647           7 :                 zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
     648           7 :                 ce = Z_PTR_P(zv) = ZCG(arena_mem);
     649           7 :                 ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_class_entry)));
     650           7 :                 zend_accel_store_interned_string(ce->name);
     651           7 :                 zend_hash_persist(&ce->function_table, zend_persist_op_array);
     652           7 :                 if (ce->default_properties_table) {
     653             :                     int i;
     654             : 
     655           0 :                         zend_accel_store(ce->default_properties_table, sizeof(zval) * ce->default_properties_count);
     656           0 :                         for (i = 0; i < ce->default_properties_count; i++) {
     657           0 :                                 zend_persist_zval(&ce->default_properties_table[i]);
     658             :                         }
     659             :                 }
     660           7 :                 if (ce->default_static_members_table) {
     661             :                     int i;
     662             : 
     663           1 :                         zend_accel_store(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count);
     664           3 :                         for (i = 0; i < ce->default_static_members_count; i++) {
     665           2 :                                 zend_persist_zval(&ce->default_static_members_table[i]);
     666             :                         }
     667             :                 }
     668           7 :                 ce->static_members_table = NULL;
     669             : 
     670           7 :                 zend_hash_persist(&ce->constants_table, zend_persist_class_constant);
     671             : 
     672           7 :                 if (ce->info.user.filename) {
     673             :                         /* do not free! PHP has centralized filename storage, compiler will free it */
     674          14 :                         zend_accel_memdup_string(ce->info.user.filename);
     675             :                 }
     676           7 :                 if (ce->info.user.doc_comment) {
     677           0 :                         if (ZCG(accel_directives).save_comments) {
     678           0 :                                 zend_accel_store_string(ce->info.user.doc_comment);
     679             :                         } else {
     680           0 :                                 if (!zend_shared_alloc_get_xlat_entry(ce->info.user.doc_comment)) {
     681           0 :                                         zend_shared_alloc_register_xlat_entry(ce->info.user.doc_comment, ce->info.user.doc_comment);
     682           0 :                                         zend_string_release(ce->info.user.doc_comment);
     683             :                                 }
     684           0 :                                 ce->info.user.doc_comment = NULL;
     685             :                         }
     686             :                 }
     687           7 :                 zend_hash_persist(&ce->properties_info, zend_persist_property_info);
     688           7 :                 if (ce->num_interfaces && ce->interfaces) {
     689           0 :                         efree(ce->interfaces);
     690             :                 }
     691           7 :                 ce->interfaces = NULL; /* will be filled in on fetch */
     692             : 
     693           7 :                 if (ce->num_traits && ce->traits) {
     694           0 :                         efree(ce->traits);
     695             :                 }
     696           7 :                 ce->traits = NULL;
     697             : 
     698           7 :                 if (ce->trait_aliases) {
     699           0 :                         int i = 0;
     700           0 :                         while (ce->trait_aliases[i]) {
     701           0 :                                 if (ce->trait_aliases[i]->trait_method) {
     702           0 :                                         if (ce->trait_aliases[i]->trait_method->method_name) {
     703           0 :                                                 zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->method_name);
     704             :                                         }
     705           0 :                                         if (ce->trait_aliases[i]->trait_method->class_name) {
     706           0 :                                                 zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->class_name);
     707             :                                         }
     708           0 :                                         ce->trait_aliases[i]->trait_method->ce = NULL;
     709           0 :                                         zend_accel_store(ce->trait_aliases[i]->trait_method,
     710             :                                                 sizeof(zend_trait_method_reference));
     711             :                                 }
     712             : 
     713           0 :                                 if (ce->trait_aliases[i]->alias) {
     714           0 :                                         zend_accel_store_interned_string(ce->trait_aliases[i]->alias);
     715             :                                 }
     716             : 
     717           0 :                                 zend_accel_store(ce->trait_aliases[i], sizeof(zend_trait_alias));
     718           0 :                                 i++;
     719             :                         }
     720             : 
     721           0 :                         zend_accel_store(ce->trait_aliases, sizeof(zend_trait_alias*) * (i + 1));
     722             :                 }
     723             : 
     724           7 :                 if (ce->trait_precedences) {
     725           0 :                         int i = 0;
     726             : 
     727           0 :                         while (ce->trait_precedences[i]) {
     728           0 :                                 zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->method_name);
     729           0 :                                 zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->class_name);
     730           0 :                                 ce->trait_precedences[i]->trait_method->ce = NULL;
     731           0 :                                 zend_accel_store(ce->trait_precedences[i]->trait_method,
     732             :                                         sizeof(zend_trait_method_reference));
     733             : 
     734           0 :                                 if (ce->trait_precedences[i]->exclude_from_classes) {
     735           0 :                                         int j = 0;
     736             : 
     737           0 :                                         while (ce->trait_precedences[i]->exclude_from_classes[j].class_name) {
     738           0 :                                                 zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_from_classes[j].class_name);
     739           0 :                                                 j++;
     740             :                                         }
     741           0 :                                         zend_accel_store(ce->trait_precedences[i]->exclude_from_classes,
     742             :                                                 sizeof(zend_class_entry*) * (j + 1));
     743             :                                 }
     744             : 
     745           0 :                                 zend_accel_store(ce->trait_precedences[i], sizeof(zend_trait_precedence));
     746           0 :                                 i++;
     747             :                         }
     748           0 :                         zend_accel_store(
     749             :                                 ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1));
     750             :                 }
     751             :         }
     752           7 : }
     753             : 
     754             : //static int zend_update_property_info_ce(zval *zv)
     755             : //{
     756             : //      zend_property_info *prop = Z_PTR_P(zv);
     757             : //
     758             : //      prop->ce = zend_shared_alloc_get_xlat_entry(prop->ce);
     759             : //      return 0;
     760             : //}
     761             : 
     762           7 : static int zend_update_parent_ce(zval *zv)
     763             : {
     764           7 :         zend_class_entry *ce = Z_PTR_P(zv);
     765             : 
     766           7 :         if (ce->parent) {
     767           3 :                 ce->parent = zend_shared_alloc_get_xlat_entry(ce->parent);
     768             :         }
     769             : 
     770             :         /* update methods */
     771           7 :         if (ce->constructor) {
     772           0 :                 ce->constructor = zend_shared_alloc_get_xlat_entry(ce->constructor);
     773             :         }
     774           7 :         if (ce->destructor) {
     775           0 :                 ce->destructor = zend_shared_alloc_get_xlat_entry(ce->destructor);
     776             :         }
     777           7 :         if (ce->clone) {
     778           0 :                 ce->clone = zend_shared_alloc_get_xlat_entry(ce->clone);
     779             :         }
     780           7 :         if (ce->__get) {
     781           0 :                 ce->__get = zend_shared_alloc_get_xlat_entry(ce->__get);
     782             :         }
     783           7 :         if (ce->__set) {
     784           0 :                 ce->__set = zend_shared_alloc_get_xlat_entry(ce->__set);
     785             :         }
     786           7 :         if (ce->__call) {
     787           0 :                 ce->__call = zend_shared_alloc_get_xlat_entry(ce->__call);
     788             :         }
     789           7 :         if (ce->serialize_func) {
     790           0 :                 ce->serialize_func = zend_shared_alloc_get_xlat_entry(ce->serialize_func);
     791             :         }
     792           7 :         if (ce->unserialize_func) {
     793           0 :                 ce->unserialize_func = zend_shared_alloc_get_xlat_entry(ce->unserialize_func);
     794             :         }
     795           7 :         if (ce->__isset) {
     796           0 :                 ce->__isset = zend_shared_alloc_get_xlat_entry(ce->__isset);
     797             :         }
     798           7 :         if (ce->__unset) {
     799           0 :                 ce->__unset = zend_shared_alloc_get_xlat_entry(ce->__unset);
     800             :         }
     801           7 :         if (ce->__tostring) {
     802           0 :                 ce->__tostring = zend_shared_alloc_get_xlat_entry(ce->__tostring);
     803             :         }
     804           7 :         if (ce->__callstatic) {
     805           0 :                 ce->__callstatic = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
     806             :         }
     807           7 :         if (ce->__debugInfo) {
     808           0 :                 ce->__debugInfo = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
     809             :         }
     810             : //      zend_hash_apply(&ce->properties_info, (apply_func_t) zend_update_property_info_ce);
     811           7 :         return 0;
     812             : }
     813             : 
     814         433 : static void zend_accel_persist_class_table(HashTable *class_table)
     815             : {
     816         433 :     zend_hash_persist(class_table, zend_persist_class_entry);
     817         433 :         zend_hash_apply(class_table, (apply_func_t) zend_update_parent_ce);
     818         433 : }
     819             : 
     820         433 : zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length)
     821             : {
     822         433 :         script->mem = ZCG(mem);
     823             : 
     824             :         ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
     825         433 :         zend_shared_alloc_clear_xlat_table();
     826             : 
     827         433 :         zend_accel_store(script, sizeof(zend_persistent_script));
     828         433 :         if (key && *key) {
     829         433 :                 *key = zend_accel_memdup(*key, key_length + 1);
     830             :         }
     831        1299 :         zend_accel_store_string(script->script.filename);
     832             : 
     833             : #ifdef __SSE2__
     834             :         /* Align to 64-byte boundary */
     835         433 :         ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
     836             : #else
     837             :         ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
     838             : #endif
     839             : 
     840         433 :         script->arena_mem = ZCG(arena_mem) = ZCG(mem);
     841         433 :         ZCG(mem) = (void*)((char*)ZCG(mem) + script->arena_size);
     842             : 
     843         433 :         zend_accel_persist_class_table(&script->script.class_table);
     844         433 :         zend_hash_persist(&script->script.function_table, zend_persist_op_array);
     845         433 :         zend_persist_op_array_ex(&script->script.main_op_array, script);
     846             : 
     847         433 :         return script;
     848             : }
     849             : 
     850         433 : int zend_accel_script_persistable(zend_persistent_script *script)
     851             : {
     852         433 :         return 1;
     853             : }

Generated by: LCOV version 1.10

Generated at Sun, 28 Aug 2016 17:10:05 +0000 (38 hours ago)

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