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 - Zend - zend_string.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 86 92 93.5 %
Date: 2015-07-26 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2015 Zend Technologies Ltd. (http://www.zend.com) |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt.                                |
      11             :    | If you did not receive a copy of the Zend license and are unable to  |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@zend.com so we can mail you a copy immediately.              |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Dmitry Stogov <dmitry@zend.com>                             |
      16             :    +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : /* $Id: $ */
      20             : 
      21             : #include "zend.h"
      22             : #include "zend_globals.h"
      23             : 
      24             : ZEND_API zend_string *(*zend_new_interned_string)(zend_string *str);
      25             : ZEND_API void (*zend_interned_strings_snapshot)(void);
      26             : ZEND_API void (*zend_interned_strings_restore)(void);
      27             : 
      28             : static zend_string *zend_new_interned_string_int(zend_string *str);
      29             : static void zend_interned_strings_snapshot_int(void);
      30             : static void zend_interned_strings_restore_int(void);
      31             : 
      32   309049084 : ZEND_API zend_ulong zend_hash_func(const char *str, size_t len)
      33             : {
      34   309049084 :         return zend_inline_hash_func(str, len);
      35             : }
      36             : 
      37             : #ifndef ZTS
      38    87628702 : static void _str_dtor(zval *zv)
      39             : {
      40    87628702 :         zend_string *str = Z_STR_P(zv);
      41    87628702 :         pefree(str, GC_FLAGS(str) & IS_STR_PERSISTENT);
      42    87628702 : }
      43             : #endif
      44             : 
      45       21049 : void zend_interned_strings_init(void)
      46             : {
      47             : #ifndef ZTS
      48             :         zend_string *str;
      49             : 
      50       21049 :         zend_hash_init(&CG(interned_strings), 1024, NULL, _str_dtor, 1);
      51             : 
      52       21049 :         CG(interned_strings).nTableMask = -CG(interned_strings).nTableSize;
      53       42098 :         HT_SET_DATA_ADDR(&CG(interned_strings), pemalloc(HT_SIZE(&CG(interned_strings)), 1));
      54       21049 :         HT_HASH_RESET(&CG(interned_strings));
      55       21049 :         CG(interned_strings).u.flags |= HASH_FLAG_INITIALIZED;
      56             : 
      57             :         /* interned empty string */
      58       21049 :         str = zend_string_alloc(sizeof("")-1, 1);
      59       21049 :         str->val[0] = '\000';
      60       21049 :         CG(empty_string) = zend_new_interned_string_int(str);
      61             : #endif
      62             : 
      63             :         /* one char strings (the actual interned strings are going to be created by ext/opcache) */
      64       21049 :         memset(CG(one_char_string), 0, sizeof(CG(one_char_string)));
      65             : 
      66       21049 :         zend_new_interned_string = zend_new_interned_string_int;
      67       21049 :         zend_interned_strings_snapshot = zend_interned_strings_snapshot_int;
      68       21049 :         zend_interned_strings_restore = zend_interned_strings_restore_int;
      69       21049 : }
      70             : 
      71       21085 : void zend_interned_strings_dtor(void)
      72             : {
      73             : #ifndef ZTS
      74       21085 :         zend_hash_destroy(&CG(interned_strings));
      75             : #endif
      76       21085 : }
      77             : 
      78   166045501 : static zend_string *zend_new_interned_string_int(zend_string *str)
      79             : {
      80             : #ifndef ZTS
      81             :         zend_ulong h;
      82             :         uint nIndex;
      83             :         uint idx;
      84             :         Bucket *p;
      85             : 
      86   166045501 :         if (IS_INTERNED(str)) {
      87       73453 :                 return str;
      88             :         }
      89             : 
      90   165972048 :         h = zend_string_hash_val(str);
      91   165972048 :         nIndex = h | CG(interned_strings).nTableMask;
      92   165972048 :         idx = HT_HASH(&CG(interned_strings), nIndex);
      93   398116735 :         while (idx != HT_INVALID_IDX) {
      94   144247152 :                 p = HT_HASH_TO_BUCKET(&CG(interned_strings), idx);
      95   144247152 :                 if ((p->h == h) && (p->key->len == str->len)) {
      96    78074522 :                         if (!memcmp(p->key->val, str->val, str->len)) {
      97             :                                 zend_string_release(str);
      98    78074513 :                                 return p->key;
      99             :                         }
     100             :                 }
     101    66172639 :                 idx = Z_NEXT(p->val);
     102             :         }
     103             : 
     104    87897535 :         GC_REFCOUNT(str) = 1;
     105    87897535 :         GC_FLAGS(str) |= IS_STR_INTERNED;
     106             : 
     107    87897535 :         if (CG(interned_strings).nNumUsed >= CG(interned_strings).nTableSize) {
     108       63150 :                 if (CG(interned_strings).nTableSize < HT_MAX_SIZE) { /* Let's double the table size */
     109             :                         void *new_data;
     110       63150 :                         void *old_data = HT_GET_DATA_ADDR(&CG(interned_strings));
     111       63150 :                         Bucket *old_buckets = CG(interned_strings).arData;
     112             : 
     113       63150 :                         HANDLE_BLOCK_INTERRUPTIONS();
     114       63150 :                         CG(interned_strings).nTableSize += CG(interned_strings).nTableSize;
     115       63150 :                         CG(interned_strings).nTableMask = -CG(interned_strings).nTableSize;
     116       63150 :                         new_data = malloc(HT_SIZE(&CG(interned_strings)));
     117             : 
     118       63150 :                         if (new_data) {
     119       63150 :                                 HT_SET_DATA_ADDR(&CG(interned_strings), new_data);
     120       63150 :                                 memcpy(CG(interned_strings).arData, old_buckets, sizeof(Bucket) * CG(interned_strings).nNumUsed);
     121       63150 :                                 free(old_data);
     122       63150 :                                 zend_hash_rehash(&CG(interned_strings));
     123             :                         } else {
     124           0 :                                 CG(interned_strings).nTableSize = CG(interned_strings).nTableSize >> 1;
     125           0 :                                 CG(interned_strings).nTableMask = -CG(interned_strings).nTableSize;
     126             :                         }
     127       63150 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     128             :                 }
     129             :         }
     130             : 
     131    87897535 :         HANDLE_BLOCK_INTERRUPTIONS();
     132             : 
     133    87897535 :         idx = CG(interned_strings).nNumUsed++;
     134    87897535 :         CG(interned_strings).nNumOfElements++;
     135    87897535 :         p = CG(interned_strings).arData + idx;
     136    87897535 :         p->h = h;
     137    87897535 :         p->key = str;
     138    87897535 :         Z_STR(p->val) = str;
     139    87897535 :         Z_TYPE_INFO(p->val) = IS_INTERNED_STRING_EX;
     140    87897535 :         nIndex = h | CG(interned_strings).nTableMask;
     141    87897535 :         Z_NEXT(p->val) = HT_HASH(&CG(interned_strings), nIndex);
     142    87897535 :         HT_HASH(&CG(interned_strings), nIndex) = HT_IDX_TO_HASH(idx);
     143             : 
     144    87897535 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     145             : 
     146    87897535 :         return str;
     147             : #else
     148             :         return str;
     149             : #endif
     150             : }
     151             : 
     152       20675 : static void zend_interned_strings_snapshot_int(void)
     153             : {
     154             : #ifndef ZTS
     155             :         uint idx;
     156             :         Bucket *p;
     157             : 
     158       20675 :         idx = CG(interned_strings).nNumUsed;
     159    85965730 :         while (idx > 0) {
     160    85924380 :                 idx--;
     161    85924380 :                 p = CG(interned_strings).arData + idx;
     162             :                 ZEND_ASSERT(GC_FLAGS(p->key) & IS_STR_PERSISTENT);
     163    85924380 :                 GC_FLAGS(p->key) |= IS_STR_PERMANENT;
     164             :         }
     165             : #endif
     166       20675 : }
     167             : 
     168       20670 : static void zend_interned_strings_restore_int(void)
     169             : {
     170             : #ifndef ZTS
     171             :         uint nIndex;
     172             :         uint idx;
     173             :         Bucket *p;
     174             : 
     175       20670 :         idx = CG(interned_strings).nNumUsed;
     176      465904 :         while (idx > 0) {
     177      445234 :                 idx--;
     178      445234 :                 p = CG(interned_strings).arData + idx;
     179      445234 :                 if (GC_FLAGS(p->key) & IS_STR_PERMANENT) break;
     180      424564 :                 CG(interned_strings).nNumUsed--;
     181      424564 :                 CG(interned_strings).nNumOfElements--;
     182             : 
     183      424564 :                 GC_FLAGS(p->key) &= ~IS_STR_INTERNED;
     184      424564 :                 GC_REFCOUNT(p->key) = 1;
     185      424564 :                 zend_string_free(p->key);
     186             : 
     187      424564 :                 nIndex = p->h | CG(interned_strings).nTableMask;
     188      424564 :                 if (HT_HASH(&CG(interned_strings), nIndex) == HT_IDX_TO_HASH(idx)) {
     189      424564 :                         HT_HASH(&CG(interned_strings), nIndex) = Z_NEXT(p->val);
     190             :                 } else {
     191           0 :                         uint32_t prev = HT_HASH(&CG(interned_strings), nIndex);
     192           0 :                         while (Z_NEXT(HT_HASH_TO_BUCKET(&CG(interned_strings), prev)->val) != idx) {
     193           0 :                                 prev = Z_NEXT(HT_HASH_TO_BUCKET(&CG(interned_strings), prev)->val);
     194             :                         }
     195           0 :                         Z_NEXT(HT_HASH_TO_BUCKET(&CG(interned_strings), prev)->val) = Z_NEXT(p->val);
     196             :                 }
     197             :         }
     198             : #endif
     199       20670 : }
     200             : 
     201             : /*
     202             :  * Local variables:
     203             :  * tab-width: 4
     204             :  * c-basic-offset: 4
     205             :  * indent-tabs-mode: t
     206             :  * End:
     207             :  */

Generated by: LCOV version 1.10

Generated at Mon, 27 Jul 2015 02:32:11 +0000 (3 days ago)

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