From 8dedaf8512d7292c9df90bebae91362ba36e7a97 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 1 Apr 2014 18:06:50 +0400 Subject: [PATCH] Use interned strings for one character strings --- Zend/zend_execute.c | 12 +++++++++--- Zend/zend_globals.h | 1 + Zend/zend_string.c | 3 +++ ext/opcache/ZendAccelerator.c | 6 ++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index e2de52c777..bdc0e2e8db 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1225,7 +1225,7 @@ static void zend_fetch_dimension_address_read(zval *result, zval *container, zva zval tmp; zend_string *str; - if (Z_TYPE_P(dim) != IS_LONG) { + if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) { switch(Z_TYPE_P(dim)) { /* case IS_LONG: */ case IS_STRING: @@ -1253,13 +1253,19 @@ static void zend_fetch_dimension_address_read(zval *result, zval *container, zva dim = &tmp; } - if (Z_LVAL_P(dim) < 0 || Z_STRLEN_P(container) <= Z_LVAL_P(dim)) { + if (UNEXPECTED(Z_LVAL_P(dim) < 0) || UNEXPECTED(Z_STRLEN_P(container) <= Z_LVAL_P(dim))) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Uninitialized string offset: %ld", Z_LVAL_P(dim)); } str = STR_EMPTY_ALLOC(); } else { - str = STR_INIT(Z_STRVAL_P(container) + Z_LVAL_P(dim), 1, 0); + zend_uchar c = (zend_uchar)Z_STRVAL_P(container)[Z_LVAL_P(dim)]; + + if (CG(one_char_string)[c]) { + str = CG(one_char_string)[c]; + } else { + str = STR_INIT(Z_STRVAL_P(container) + Z_LVAL_P(dim), 1, 0); + } } ZVAL_STR(result, str); return; diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 9dae1fcfca..828acfa106 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -141,6 +141,7 @@ struct _zend_compiler_globals { zend_stack context_stack; zend_string *empty_string; + zend_string *one_char_string[256]; HashTable interned_strings; diff --git a/Zend/zend_string.c b/Zend/zend_string.c index 170cb2c200..abd784ed5f 100644 --- a/Zend/zend_string.c +++ b/Zend/zend_string.c @@ -57,6 +57,9 @@ void zend_interned_strings_init(TSRMLS_D) str = STR_ALLOC(sizeof("")-1, 1); str->val[0] = '\000'; CG(empty_string) = zend_new_interned_string_int(str TSRMLS_CC); + + /* one char strings (the actual interned strings are going to be created by ext/opcache) */ + memset(CG(one_char_string), 0, sizeof(CG(one_char_string))); #else str = STR_ALLOC(sizeof("")-1, 1); str->val[0] = '\000'; diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 1bf672e3df..cb93fbf633 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -382,6 +382,12 @@ static void accel_use_shm_interned_strings(TSRMLS_D) #if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO /* empty string */ CG(empty_string) = accel_new_interned_string(CG(empty_string) TSRMLS_CC); + for (j = 0; j < 256; j++) { + char s[2]; + s[0] = j; + s[1] = 0; + CG(one_char_string)[j] = accel_new_interned_string(STR_INIT(s, 1, 0) TSRMLS_CC); + } #endif /* function table hash keys */ -- 2.40.0