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: 102 108 94.4 %
Date: 2016-08-28 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2016 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   362701391 : ZEND_API zend_ulong zend_hash_func(const char *str, size_t len)
      33             : {
      34   362701391 :         return zend_inline_hash_func(str, len);
      35             : }
      36             : 
      37             : #ifndef ZTS
      38   102157310 : static void _str_dtor(zval *zv)
      39             : {
      40   102157310 :         zend_string *str = Z_STR_P(zv);
      41   102157310 :         pefree(str, GC_FLAGS(str) & IS_STR_PERSISTENT);
      42   102157310 : }
      43             : #endif
      44             : 
      45             : /* Readonly, so assigned also per thread. */
      46             : static const zend_string **known_interned_strings = NULL;
      47             : static uint32_t known_interned_strings_count = 0;
      48             : 
      49       23504 : ZEND_API uint32_t zend_intern_known_strings(const char **strings, uint32_t count)
      50             : {
      51       23504 :         uint32_t i, old_count = known_interned_strings_count;
      52             : 
      53       23504 :         known_interned_strings = perealloc(known_interned_strings, sizeof(char*) * (old_count + count), 1);
      54      705120 :         for (i = 0; i < count; i++) {
      55             : #ifndef ZTS
      56     1363232 :                 zend_string *str = zend_string_init(strings[i], strlen(strings[i]), 1);
      57     1363232 :                 known_interned_strings[known_interned_strings_count + i] =
      58      681616 :                         zend_new_interned_string_int(str);
      59             : #else
      60             :                 known_interned_strings[known_interned_strings_count + i] =
      61             :                         zend_zts_interned_string_init(strings[i], strlen(strings[i]));
      62             : #endif
      63             :         }
      64       23504 :         known_interned_strings_count = old_count + count;
      65       23504 :         return old_count;
      66             : }
      67             : 
      68             : static const char *known_strings[] = {
      69             : #define _ZEND_STR_DSC(id, str) str,
      70             : ZEND_KNOWN_STRINGS(_ZEND_STR_DSC)
      71             : #undef _ZEND_STR_DSC
      72             :         NULL
      73             : };
      74             : 
      75       23504 : void zend_known_interned_strings_init(zend_string ***strings, uint32_t *count)
      76             : {
      77       23504 :         *strings = (zend_string **)known_interned_strings;
      78       23504 :         *count   = known_interned_strings_count;
      79       23504 : }
      80             : 
      81       23504 : void zend_interned_strings_init(void)
      82             : {
      83             : #ifndef ZTS
      84             :         zend_string *str;
      85             : 
      86       23504 :         zend_hash_init(&CG(interned_strings), 1024, NULL, _str_dtor, 1);
      87             : 
      88       23504 :         CG(interned_strings).nTableMask = -CG(interned_strings).nTableSize;
      89       23504 :         HT_SET_DATA_ADDR(&CG(interned_strings), pemalloc(HT_SIZE(&CG(interned_strings)), 1));
      90       23504 :         HT_HASH_RESET(&CG(interned_strings));
      91       23504 :         CG(interned_strings).u.flags |= HASH_FLAG_INITIALIZED;
      92             : 
      93             :         /* interned empty string */
      94       23504 :         str = zend_string_alloc(sizeof("")-1, 1);
      95       23504 :         ZSTR_VAL(str)[0] = '\000';
      96       23504 :         CG(empty_string) = zend_new_interned_string_int(str);
      97             : #endif
      98             : 
      99             :         /* one char strings (the actual interned strings are going to be created by ext/opcache) */
     100       23504 :         memset(CG(one_char_string), 0, sizeof(CG(one_char_string)));
     101             : 
     102             :         /* known strings */
     103       23504 :         zend_intern_known_strings(known_strings, (sizeof(known_strings) / sizeof(known_strings[0])) - 1);
     104       23504 :         zend_known_interned_strings_init(&CG(known_strings), &CG(known_strings_count));
     105             : 
     106       23504 :         zend_new_interned_string = zend_new_interned_string_int;
     107       23504 :         zend_interned_strings_snapshot = zend_interned_strings_snapshot_int;
     108       23504 :         zend_interned_strings_restore = zend_interned_strings_restore_int;
     109       23504 : }
     110             : 
     111       23544 : void zend_interned_strings_dtor(void)
     112             : {
     113             : #ifndef ZTS
     114       23544 :         zend_hash_destroy(&CG(interned_strings));
     115             : #else
     116             :         uint32_t i;
     117             : 
     118             :         for (i = 0; i < CG(known_strings_count); i++) {
     119             :                 zend_zts_interned_string_free(&CG(known_strings)[i]);
     120             :         }
     121             : #endif
     122       23544 :         free(CG(known_strings));
     123       23544 :         CG(known_strings) = NULL;
     124       23544 :         CG(known_strings_count) = 0;
     125       23544 :         known_interned_strings = NULL;
     126       23544 :         known_interned_strings_count = 0;
     127       23544 : }
     128             : 
     129   194862734 : static zend_string *zend_new_interned_string_int(zend_string *str)
     130             : {
     131             : #ifndef ZTS
     132             :         zend_ulong h;
     133             :         uint nIndex;
     134             :         uint idx;
     135             :         Bucket *p;
     136             : 
     137   194862734 :         if (ZSTR_IS_INTERNED(str)) {
     138       83251 :                 return str;
     139             :         }
     140             : 
     141   194779483 :         h = zend_string_hash_val(str);
     142   194779483 :         nIndex = h | CG(interned_strings).nTableMask;
     143   194779483 :         idx = HT_HASH(&CG(interned_strings), nIndex);
     144   465349634 :         while (idx != HT_INVALID_IDX) {
     145   168113969 :                 p = HT_HASH_TO_BUCKET(&CG(interned_strings), idx);
     146   168113969 :                 if ((p->h == h) && (ZSTR_LEN(p->key) == ZSTR_LEN(str))) {
     147    92323310 :                         if (!memcmp(ZSTR_VAL(p->key), ZSTR_VAL(str), ZSTR_LEN(str))) {
     148             :                                 zend_string_release(str);
     149    92323301 :                                 return p->key;
     150             :                         }
     151             :                 }
     152    75790668 :                 idx = Z_NEXT(p->val);
     153             :         }
     154             : 
     155   102456182 :         GC_REFCOUNT(str) = 1;
     156   102456182 :         GC_FLAGS(str) |= IS_STR_INTERNED;
     157             : 
     158   102456182 :         if (CG(interned_strings).nNumUsed >= CG(interned_strings).nTableSize) {
     159       70515 :                 if (CG(interned_strings).nTableSize < HT_MAX_SIZE) { /* Let's double the table size */
     160             :                         void *new_data;
     161       70515 :                         void *old_data = HT_GET_DATA_ADDR(&CG(interned_strings));
     162       70515 :                         Bucket *old_buckets = CG(interned_strings).arData;
     163             : 
     164       70515 :                         CG(interned_strings).nTableSize += CG(interned_strings).nTableSize;
     165       70515 :                         CG(interned_strings).nTableMask = -CG(interned_strings).nTableSize;
     166       70515 :                         new_data = malloc(HT_SIZE(&CG(interned_strings)));
     167             : 
     168       70515 :                         if (new_data) {
     169       70515 :                                 HT_SET_DATA_ADDR(&CG(interned_strings), new_data);
     170       70515 :                                 memcpy(CG(interned_strings).arData, old_buckets, sizeof(Bucket) * CG(interned_strings).nNumUsed);
     171       70515 :                                 free(old_data);
     172       70515 :                                 zend_hash_rehash(&CG(interned_strings));
     173             :                         } else {
     174           0 :                                 CG(interned_strings).nTableSize = CG(interned_strings).nTableSize >> 1;
     175           0 :                                 CG(interned_strings).nTableMask = -CG(interned_strings).nTableSize;
     176             :                         }
     177             :                 }
     178             :         }
     179             : 
     180   102456182 :         idx = CG(interned_strings).nNumUsed++;
     181   102456182 :         CG(interned_strings).nNumOfElements++;
     182   102456182 :         p = CG(interned_strings).arData + idx;
     183   102456182 :         p->h = h;
     184   102456182 :         p->key = str;
     185   102456182 :         Z_STR(p->val) = str;
     186   102456182 :         Z_TYPE_INFO(p->val) = IS_INTERNED_STRING_EX;
     187   102456182 :         nIndex = h | CG(interned_strings).nTableMask;
     188   102456182 :         Z_NEXT(p->val) = HT_HASH(&CG(interned_strings), nIndex);
     189   102456182 :         HT_HASH(&CG(interned_strings), nIndex) = HT_IDX_TO_HASH(idx);
     190             : 
     191   102456182 :         return str;
     192             : #else
     193             :         return str;
     194             : #endif
     195             : }
     196             : 
     197       23124 : static void zend_interned_strings_snapshot_int(void)
     198             : {
     199             : #ifndef ZTS
     200             :         uint idx;
     201             :         Bucket *p;
     202             : 
     203       23124 :         idx = CG(interned_strings).nNumUsed;
     204   100380810 :         while (idx > 0) {
     205   100334562 :                 idx--;
     206   100334562 :                 p = CG(interned_strings).arData + idx;
     207             :                 ZEND_ASSERT(GC_FLAGS(p->key) & IS_STR_PERSISTENT);
     208   100334562 :                 GC_FLAGS(p->key) |= IS_STR_PERMANENT;
     209             :         }
     210             : #endif
     211       23124 : }
     212             : 
     213       23120 : static void zend_interned_strings_restore_int(void)
     214             : {
     215             : #ifndef ZTS
     216             :         uint nIndex;
     217             :         uint idx;
     218             :         Bucket *p;
     219             : 
     220       23120 :         idx = CG(interned_strings).nNumUsed;
     221      525657 :         while (idx > 0) {
     222      502537 :                 idx--;
     223      502537 :                 p = CG(interned_strings).arData + idx;
     224      502537 :                 if (GC_FLAGS(p->key) & IS_STR_PERMANENT) break;
     225      479417 :                 CG(interned_strings).nNumUsed--;
     226      479417 :                 CG(interned_strings).nNumOfElements--;
     227             : 
     228      479417 :                 GC_FLAGS(p->key) &= ~IS_STR_INTERNED;
     229      479417 :                 GC_REFCOUNT(p->key) = 1;
     230      479417 :                 zend_string_free(p->key);
     231             : 
     232      479417 :                 nIndex = p->h | CG(interned_strings).nTableMask;
     233      479417 :                 if (HT_HASH(&CG(interned_strings), nIndex) == HT_IDX_TO_HASH(idx)) {
     234      479417 :                         HT_HASH(&CG(interned_strings), nIndex) = Z_NEXT(p->val);
     235             :                 } else {
     236           0 :                         uint32_t prev = HT_HASH(&CG(interned_strings), nIndex);
     237           0 :                         while (Z_NEXT(HT_HASH_TO_BUCKET(&CG(interned_strings), prev)->val) != idx) {
     238           0 :                                 prev = Z_NEXT(HT_HASH_TO_BUCKET(&CG(interned_strings), prev)->val);
     239             :                         }
     240           0 :                         Z_NEXT(HT_HASH_TO_BUCKET(&CG(interned_strings), prev)->val) = Z_NEXT(p->val);
     241             :                 }
     242             :         }
     243             : #endif
     244       23120 : }
     245             : 
     246             : /*
     247             :  * Local variables:
     248             :  * tab-width: 4
     249             :  * c-basic-offset: 4
     250             :  * indent-tabs-mode: t
     251             :  * End:
     252             :  */

Generated by: LCOV version 1.10

Generated at Sun, 28 Aug 2016 17:09:53 +0000 (14 hours ago)

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