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: 85 89 95.5 %
Date: 2014-09-27 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2014 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 TSRMLS_DC);
      25             : ZEND_API void (*zend_interned_strings_snapshot)(TSRMLS_D);
      26             : ZEND_API void (*zend_interned_strings_restore)(TSRMLS_D);
      27             : 
      28             : static zend_string *zend_new_interned_string_int(zend_string *str TSRMLS_DC);
      29             : static void zend_interned_strings_snapshot_int(TSRMLS_D);
      30             : static void zend_interned_strings_restore_int(TSRMLS_D);
      31             : 
      32   296076268 : ZEND_API zend_ulong zend_hash_func(const char *str, size_t len)
      33             : {
      34   296076268 :         return zend_inline_hash_func(str, len);
      35             : }
      36             : 
      37             : #ifndef ZTS
      38    86334228 : static void _str_dtor(zval *zv)
      39             : {
      40    86334228 :         zend_string *str = Z_STR_P(zv);
      41    86334228 :         GC_FLAGS(str) &= ~IS_STR_INTERNED;
      42    86334228 :         GC_REFCOUNT(str) = 1;
      43    86334228 : }
      44             : #endif
      45             : 
      46       20352 : void zend_interned_strings_init(TSRMLS_D)
      47             : {
      48             :         zend_string *str;
      49             : 
      50             : #ifndef ZTS
      51       20352 :         zend_hash_init(&CG(interned_strings), 1024, NULL, _str_dtor, 1);
      52             :         
      53       20352 :         CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
      54       40704 :         CG(interned_strings).arData = (Bucket*) pecalloc(CG(interned_strings).nTableSize, sizeof(Bucket), 1);
      55       40704 :         CG(interned_strings).arHash = (uint32_t*) pecalloc(CG(interned_strings).nTableSize, sizeof(uint32_t), 1);
      56       20352 :         memset(CG(interned_strings).arHash, INVALID_IDX, CG(interned_strings).nTableSize * sizeof(uint32_t));
      57             : 
      58             :         /* interned empty string */
      59       20352 :         str = zend_string_alloc(sizeof("")-1, 1);
      60       20352 :         str->val[0] = '\000';
      61       20352 :         CG(empty_string) = zend_new_interned_string_int(str TSRMLS_CC);
      62             : #else
      63             :         str = zend_string_alloc(sizeof("")-1, 1);
      64             :         str->val[0] = '\000';
      65             :         zend_string_hash_val(str);
      66             :         str->gc.u.v.flags |= IS_STR_INTERNED;
      67             :         CG(empty_string) = str;
      68             : #endif
      69             : 
      70             :         /* one char strings (the actual interned strings are going to be created by ext/opcache) */
      71       20352 :         memset(CG(one_char_string), 0, sizeof(CG(one_char_string)));
      72             : 
      73       20352 :         zend_new_interned_string = zend_new_interned_string_int;
      74       20352 :         zend_interned_strings_snapshot = zend_interned_strings_snapshot_int;
      75       20352 :         zend_interned_strings_restore = zend_interned_strings_restore_int;
      76       20352 : }
      77             : 
      78       20386 : void zend_interned_strings_dtor(TSRMLS_D)
      79             : {
      80             : #ifndef ZTS
      81       20386 :         zend_hash_destroy(&CG(interned_strings));
      82             : #else
      83             :         zend_string_release(CG(empty_string));
      84             : #endif
      85       20386 : }
      86             : 
      87   163915453 : static zend_string *zend_new_interned_string_int(zend_string *str TSRMLS_DC)
      88             : {
      89             : #ifndef ZTS
      90             :         zend_ulong h;
      91             :         uint nIndex;
      92             :         uint idx;
      93             :         Bucket *p;
      94             : 
      95   163915453 :         if (IS_INTERNED(str)) {
      96       38533 :                 return str;
      97             :         }
      98             : 
      99   163876920 :         h = zend_string_hash_val(str);
     100   163876920 :         nIndex = h & CG(interned_strings).nTableMask;
     101   163876920 :         idx = CG(interned_strings).arHash[nIndex];
     102   393014026 :         while (idx != INVALID_IDX) {
     103   142530098 :                 p = CG(interned_strings).arData + idx;
     104   142530098 :                 if ((p->h == h) && (p->key->len == str->len)) {
     105    77269921 :                         if (!memcmp(p->key->val, str->val, str->len)) {
     106             :                                 zend_string_release(str);
     107    77269912 :                                 return p->key;
     108             :                         }
     109             :                 }
     110    65260186 :                 idx = Z_NEXT(p->val);
     111             :         }
     112             :         
     113    86607008 :         GC_REFCOUNT(str) = 1;
     114    86607008 :         GC_FLAGS(str) |= IS_STR_INTERNED;
     115             : 
     116    86607008 :         if (CG(interned_strings).nNumUsed >= CG(interned_strings).nTableSize) {
     117       61059 :                 if ((CG(interned_strings).nTableSize << 1) > 0) {      /* Let's double the table size */
     118      122118 :                         Bucket *d = (Bucket *) perealloc_recoverable(CG(interned_strings).arData, (CG(interned_strings).nTableSize << 1) * sizeof(Bucket), 1);
     119      122118 :                         uint32_t *h = (uint32_t *) perealloc_recoverable(CG(interned_strings).arHash, (CG(interned_strings).nTableSize << 1) * sizeof(uint32_t), 1);
     120             : 
     121      122118 :                         if (d && h) {
     122       61059 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     123       61059 :                                 CG(interned_strings).arData = d;
     124       61059 :                                 CG(interned_strings).arHash = h;
     125       61059 :                                 CG(interned_strings).nTableSize = (CG(interned_strings).nTableSize << 1);
     126       61059 :                                 CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
     127       61059 :                                 zend_hash_rehash(&CG(interned_strings));
     128       61059 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     129             :                         }
     130             :                 }
     131             :         }
     132             : 
     133    86607008 :         HANDLE_BLOCK_INTERRUPTIONS();
     134             :         
     135    86607008 :         idx = CG(interned_strings).nNumUsed++;
     136    86607008 :         CG(interned_strings).nNumOfElements++;
     137    86607008 :         p = CG(interned_strings).arData + idx;
     138    86607008 :         p->h = h;
     139    86607008 :         p->key = str;
     140    86607008 :         Z_STR(p->val) = str;
     141    86607008 :         Z_TYPE_INFO(p->val) = IS_INTERNED_STRING_EX;
     142    86607008 :         nIndex = h & CG(interned_strings).nTableMask;
     143    86607008 :         Z_NEXT(p->val) = CG(interned_strings).arHash[nIndex];
     144    86607008 :         CG(interned_strings).arHash[nIndex] = idx;
     145             :                 
     146    86607008 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     147             : 
     148    86607008 :         return str;
     149             : #else
     150             :         return str;
     151             : #endif
     152             : }
     153             : 
     154       19984 : static void zend_interned_strings_snapshot_int(TSRMLS_D)
     155             : {
     156             : #ifndef ZTS
     157             :         uint idx;
     158             :         Bucket *p;
     159             : 
     160       19984 :         idx = CG(interned_strings).nNumUsed;
     161    84671354 :         while (idx > 0) {
     162    84631386 :                 idx--;
     163    84631386 :                 p = CG(interned_strings).arData + idx;
     164             :                 ZEND_ASSERT(GC_FLAGS(p->key) & IS_STR_PERSISTENT);
     165    84631386 :                 GC_FLAGS(p->key) |= IS_STR_PERMANENT;
     166             :         }
     167             : #endif
     168       19984 : }
     169             : 
     170       19977 : static void zend_interned_strings_restore_int(TSRMLS_D)
     171             : {
     172             : #ifndef ZTS
     173             :         uint nIndex;
     174             :         uint idx;
     175             :         Bucket *p;
     176             : 
     177       19977 :         idx = CG(interned_strings).nNumUsed;
     178      462728 :         while (idx > 0) {
     179      442751 :                 idx--;
     180      442751 :                 p = CG(interned_strings).arData + idx;
     181      442751 :                 if (GC_FLAGS(p->key) & IS_STR_PERMANENT) break;
     182      422774 :                 CG(interned_strings).nNumUsed--;
     183      422774 :                 CG(interned_strings).nNumOfElements--;
     184             : 
     185      422774 :                 GC_FLAGS(p->key) &= ~IS_STR_INTERNED;
     186      422774 :                 GC_REFCOUNT(p->key) = 1;
     187      422774 :                 zend_string_free(p->key);
     188             : 
     189      422774 :                 nIndex = p->h & CG(interned_strings).nTableMask;
     190      422774 :                 if (CG(interned_strings).arHash[nIndex] == idx) {
     191      422774 :                         CG(interned_strings).arHash[nIndex] = Z_NEXT(p->val);
     192             :                 } else {
     193           0 :                         uint prev = CG(interned_strings).arHash[nIndex];
     194           0 :                         while (Z_NEXT(CG(interned_strings).arData[prev].val) != idx) {
     195           0 :                                 prev = Z_NEXT(CG(interned_strings).arData[prev].val);
     196             :                         }
     197           0 :                         Z_NEXT(CG(interned_strings).arData[prev].val) = Z_NEXT(p->val);
     198             :                 }
     199             :         }
     200             : #endif
     201       19977 : }
     202             : 
     203             : /*
     204             :  * Local variables:
     205             :  * tab-width: 4
     206             :  * c-basic-offset: 4
     207             :  * indent-tabs-mode: t
     208             :  * End:
     209             :  */

Generated by: LCOV version 1.10

Generated at Sat, 27 Sep 2014 16:43:02 +0000 (3 days ago)

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