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-10-14 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   296803377 : ZEND_API zend_ulong zend_hash_func(const char *str, size_t len)
      33             : {
      34   296803377 :         return zend_inline_hash_func(str, len);
      35             : }
      36             : 
      37             : #ifndef ZTS
      38    86541719 : static void _str_dtor(zval *zv)
      39             : {
      40    86541719 :         zend_string *str = Z_STR_P(zv);
      41    86541719 :         GC_FLAGS(str) &= ~IS_STR_INTERNED;
      42    86541719 :         GC_REFCOUNT(str) = 1;
      43    86541719 : }
      44             : #endif
      45             : 
      46       20401 : void zend_interned_strings_init(TSRMLS_D)
      47             : {
      48             : #ifndef ZTS
      49             :         zend_string *str;
      50             : 
      51       20401 :         zend_hash_init(&CG(interned_strings), 1024, NULL, _str_dtor, 1);
      52             :         
      53       20401 :         CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
      54       40802 :         CG(interned_strings).arData = (Bucket*) pecalloc(CG(interned_strings).nTableSize, sizeof(Bucket), 1);
      55       40802 :         CG(interned_strings).arHash = (uint32_t*) pecalloc(CG(interned_strings).nTableSize, sizeof(uint32_t), 1);
      56       20401 :         memset(CG(interned_strings).arHash, INVALID_IDX, CG(interned_strings).nTableSize * sizeof(uint32_t));
      57             : 
      58             :         /* interned empty string */
      59       20401 :         str = zend_string_alloc(sizeof("")-1, 1);
      60       20401 :         str->val[0] = '\000';
      61       20401 :         CG(empty_string) = zend_new_interned_string_int(str TSRMLS_CC);
      62             : #endif
      63             : 
      64             :         /* one char strings (the actual interned strings are going to be created by ext/opcache) */
      65       20401 :         memset(CG(one_char_string), 0, sizeof(CG(one_char_string)));
      66             : 
      67       20401 :         zend_new_interned_string = zend_new_interned_string_int;
      68       20401 :         zend_interned_strings_snapshot = zend_interned_strings_snapshot_int;
      69       20401 :         zend_interned_strings_restore = zend_interned_strings_restore_int;
      70       20401 : }
      71             : 
      72       20435 : void zend_interned_strings_dtor(TSRMLS_D)
      73             : {
      74             : #ifndef ZTS
      75       20435 :         zend_hash_destroy(&CG(interned_strings));
      76             : #endif
      77       20435 : }
      78             : 
      79   164307929 : static zend_string *zend_new_interned_string_int(zend_string *str TSRMLS_DC)
      80             : {
      81             : #ifndef ZTS
      82             :         zend_ulong h;
      83             :         uint nIndex;
      84             :         uint idx;
      85             :         Bucket *p;
      86             : 
      87   164307929 :         if (IS_INTERNED(str)) {
      88       38594 :                 return str;
      89             :         }
      90             : 
      91   164269335 :         h = zend_string_hash_val(str);
      92   164269335 :         nIndex = h & CG(interned_strings).nTableMask;
      93   164269335 :         idx = CG(interned_strings).arHash[nIndex];
      94   393955131 :         while (idx != INVALID_IDX) {
      95   142871410 :                 p = CG(interned_strings).arData + idx;
      96   142871410 :                 if ((p->h == h) && (p->key->len == str->len)) {
      97    77454958 :                         if (!memcmp(p->key->val, str->val, str->len)) {
      98             :                                 zend_string_release(str);
      99    77454949 :                                 return p->key;
     100             :                         }
     101             :                 }
     102    65416461 :                 idx = Z_NEXT(p->val);
     103             :         }
     104             :         
     105    86814386 :         GC_REFCOUNT(str) = 1;
     106    86814386 :         GC_FLAGS(str) |= IS_STR_INTERNED;
     107             : 
     108    86814386 :         if (CG(interned_strings).nNumUsed >= CG(interned_strings).nTableSize) {
     109       61206 :                 if ((CG(interned_strings).nTableSize << 1) > 0) {      /* Let's double the table size */
     110      122412 :                         Bucket *d = (Bucket *) perealloc_recoverable(CG(interned_strings).arData, (CG(interned_strings).nTableSize << 1) * sizeof(Bucket), 1);
     111      122412 :                         uint32_t *h = (uint32_t *) perealloc_recoverable(CG(interned_strings).arHash, (CG(interned_strings).nTableSize << 1) * sizeof(uint32_t), 1);
     112             : 
     113      122412 :                         if (d && h) {
     114       61206 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     115       61206 :                                 CG(interned_strings).arData = d;
     116       61206 :                                 CG(interned_strings).arHash = h;
     117       61206 :                                 CG(interned_strings).nTableSize = (CG(interned_strings).nTableSize << 1);
     118       61206 :                                 CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
     119       61206 :                                 zend_hash_rehash(&CG(interned_strings));
     120       61206 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     121             :                         }
     122             :                 }
     123             :         }
     124             : 
     125    86814386 :         HANDLE_BLOCK_INTERRUPTIONS();
     126             :         
     127    86814386 :         idx = CG(interned_strings).nNumUsed++;
     128    86814386 :         CG(interned_strings).nNumOfElements++;
     129    86814386 :         p = CG(interned_strings).arData + idx;
     130    86814386 :         p->h = h;
     131    86814386 :         p->key = str;
     132    86814386 :         Z_STR(p->val) = str;
     133    86814386 :         Z_TYPE_INFO(p->val) = IS_INTERNED_STRING_EX;
     134    86814386 :         nIndex = h & CG(interned_strings).nTableMask;
     135    86814386 :         Z_NEXT(p->val) = CG(interned_strings).arHash[nIndex];
     136    86814386 :         CG(interned_strings).arHash[nIndex] = idx;
     137             :                 
     138    86814386 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     139             : 
     140    86814386 :         return str;
     141             : #else
     142             :         return str;
     143             : #endif
     144             : }
     145             : 
     146       20033 : static void zend_interned_strings_snapshot_int(TSRMLS_D)
     147             : {
     148             : #ifndef ZTS
     149             :         uint idx;
     150             :         Bucket *p;
     151             : 
     152       20033 :         idx = CG(interned_strings).nNumUsed;
     153    84878943 :         while (idx > 0) {
     154    84838877 :                 idx--;
     155    84838877 :                 p = CG(interned_strings).arData + idx;
     156             :                 ZEND_ASSERT(GC_FLAGS(p->key) & IS_STR_PERSISTENT);
     157    84838877 :                 GC_FLAGS(p->key) |= IS_STR_PERMANENT;
     158             :         }
     159             : #endif
     160       20033 : }
     161             : 
     162       20026 : static void zend_interned_strings_restore_int(TSRMLS_D)
     163             : {
     164             : #ifndef ZTS
     165             :         uint nIndex;
     166             :         uint idx;
     167             :         Bucket *p;
     168             : 
     169       20026 :         idx = CG(interned_strings).nNumUsed;
     170      462713 :         while (idx > 0) {
     171      442687 :                 idx--;
     172      442687 :                 p = CG(interned_strings).arData + idx;
     173      442687 :                 if (GC_FLAGS(p->key) & IS_STR_PERMANENT) break;
     174      422661 :                 CG(interned_strings).nNumUsed--;
     175      422661 :                 CG(interned_strings).nNumOfElements--;
     176             : 
     177      422661 :                 GC_FLAGS(p->key) &= ~IS_STR_INTERNED;
     178      422661 :                 GC_REFCOUNT(p->key) = 1;
     179      422661 :                 zend_string_free(p->key);
     180             : 
     181      422661 :                 nIndex = p->h & CG(interned_strings).nTableMask;
     182      422661 :                 if (CG(interned_strings).arHash[nIndex] == idx) {
     183      422661 :                         CG(interned_strings).arHash[nIndex] = Z_NEXT(p->val);
     184             :                 } else {
     185           0 :                         uint prev = CG(interned_strings).arHash[nIndex];
     186           0 :                         while (Z_NEXT(CG(interned_strings).arData[prev].val) != idx) {
     187           0 :                                 prev = Z_NEXT(CG(interned_strings).arData[prev].val);
     188             :                         }
     189           0 :                         Z_NEXT(CG(interned_strings).arData[prev].val) = Z_NEXT(p->val);
     190             :                 }
     191             :         }
     192             : #endif
     193       20026 : }
     194             : 
     195             : /*
     196             :  * Local variables:
     197             :  * tab-width: 4
     198             :  * c-basic-offset: 4
     199             :  * indent-tabs-mode: t
     200             :  * End:
     201             :  */

Generated by: LCOV version 1.10

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

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