Skip to content

Commit dd5c478

Browse files
committed
Added concept of interned strings. All strings constants known at compile time are allocated in a single copy and never changed.
1 parent 94dd837 commit dd5c478

30 files changed

+838
-192
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
- Upgraded bundled sqlite to version 3.6.23.1. (Ilia)
55
- Upgraded bundled PCRE to version 8.02. (Ilia)
66

7+
- Added concept of interned strings. All strings constants known at compile
8+
time are allocated in a single copy and never changed. (Dmitry)
79
- Added an optimization which saves memory and emalloc/efree calls for empty
810
HashTables (Stas, Dmitry)
911
- Added Tokyo Cabinet abstract DB support to ext/dba. (Michael Maclean)

Zend/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ libZend_la_SOURCES=\
1717
zend_objects_API.c zend_ts_hash.c zend_stream.c \
1818
zend_default_classes.c \
1919
zend_iterators.c zend_interfaces.c zend_exceptions.c \
20-
zend_strtod.c zend_closures.c zend_float.c
20+
zend_strtod.c zend_closures.c zend_float.c zend_string.c
2121

2222
libZend_la_LDFLAGS =
2323
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@

Zend/Zend.dsp

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Zend/ZendTS.dsp

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Zend/zend.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
693693
EG(user_exception_handler) = NULL;
694694
#endif
695695

696+
zend_interned_strings_init(TSRMLS_C);
696697
zend_startup_builtin_functions(TSRMLS_C);
697698
zend_register_standard_constants(TSRMLS_C);
698699
zend_register_auto_global("GLOBALS", sizeof("GLOBALS") - 1, NULL TSRMLS_CC);
@@ -781,6 +782,8 @@ void zend_shutdown(TSRMLS_D) /* {{{ */
781782
GLOBAL_CONSTANTS_TABLE = NULL;
782783
#endif
783784
zend_destroy_rsrc_list_dtors();
785+
786+
zend_interned_strings_dtor(TSRMLS_C);
784787
}
785788
/* }}} */
786789

Zend/zend.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ char *alloca ();
237237
#include "zend_alloc.h"
238238

239239
#include "zend_types.h"
240+
#include "zend_string.h"
240241

241242
#ifdef HAVE_LIMITS_H
242243
# include <limits.h>
@@ -599,8 +600,8 @@ END_EXTERN_C()
599600

600601
/* FIXME: Check if we can save if (ptr) too */
601602

602-
#define STR_FREE(ptr) if (ptr) { efree(ptr); }
603-
#define STR_FREE_REL(ptr) if (ptr) { efree_rel(ptr); }
603+
#define STR_FREE(ptr) if (ptr && !IS_INTERNED(ptr)) { efree(ptr); }
604+
#define STR_FREE_REL(ptr) if (ptr && !IS_INTERNED(ptr)) { efree_rel(ptr); }
604605

605606
#define STR_EMPTY_ALLOC() estrndup("", sizeof("")-1)
606607

Zend/zend_API.c

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,10 +1893,10 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
18931893
}
18941894
}
18951895
fname_len = strlen(ptr->fname);
1896-
lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
1896+
lowercase_name = CG(new_interned_string)(zend_str_tolower_dup(ptr->fname, fname_len), fname_len + 1, 1 TSRMLS_CC);
18971897
if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)&reg_function) == FAILURE) {
18981898
unload=1;
1899-
efree(lowercase_name);
1899+
str_efree(lowercase_name);
19001900
break;
19011901
}
19021902
if (scope) {
@@ -1938,7 +1938,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
19381938
}
19391939
ptr++;
19401940
count++;
1941-
efree(lowercase_name);
1941+
str_efree(lowercase_name);
19421942
}
19431943
if (unload) { /* before unloading, display all remaining bad function in the module */
19441944
if (scope) {
@@ -2168,7 +2168,7 @@ int zend_next_free_module(void) /* {{{ */
21682168
static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */
21692169
{
21702170
zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
2171-
char *lowercase_name = malloc(orig_class_entry->name_length + 1);
2171+
char *lowercase_name = emalloc(orig_class_entry->name_length + 1);
21722172
*class_entry = *orig_class_entry;
21732173

21742174
class_entry->type = ZEND_INTERNAL_CLASS;
@@ -2181,8 +2181,9 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class
21812181
}
21822182

21832183
zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length);
2184+
lowercase_name = CG(new_interned_string)(lowercase_name, class_entry->name_length + 1, 1 TSRMLS_CC);
21842185
zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL);
2185-
free(lowercase_name);
2186+
str_efree(lowercase_name);
21862187
return class_entry;
21872188
}
21882189
/* }}} */
@@ -3070,6 +3071,7 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
30703071
{
30713072
zend_property_info property_info;
30723073
HashTable *target_symbol_table;
3074+
char *interned_name;
30733075

30743076
if (!(access_type & ZEND_ACC_PPP_MASK)) {
30753077
access_type |= ZEND_ACC_PUBLIC;
@@ -3097,7 +3099,6 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
30973099
int priv_name_length;
30983100

30993101
zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
3100-
zend_hash_update(target_symbol_table, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL);
31013102
property_info.name = priv_name;
31023103
property_info.name_length = priv_name_length;
31033104
}
@@ -3107,7 +3108,6 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
31073108
int prot_name_length;
31083109

31093110
zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
3110-
zend_hash_update(target_symbol_table, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
31113111
property_info.name = prot_name;
31123112
property_info.name_length = prot_name_length;
31133113
}
@@ -3121,11 +3121,27 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
31213121
zend_hash_del(target_symbol_table, prot_name, prot_name_length+1);
31223122
pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
31233123
}
3124-
zend_hash_update(target_symbol_table, name, name_length+1, &property, sizeof(zval *), NULL);
3125-
property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length);
3124+
if (IS_INTERNED(name)) {
3125+
property_info.name = (char*)name;
3126+
} else {
3127+
property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length);
3128+
}
31263129
property_info.name_length = name_length;
31273130
break;
31283131
}
3132+
3133+
interned_name = CG(new_interned_string)(property_info.name, property_info.name_length+1, 0 TSRMLS_CC);
3134+
if (interned_name != property_info.name) {
3135+
if (ce->type == ZEND_USER_CLASS) {
3136+
efree(property_info.name);
3137+
} else {
3138+
free(property_info.name);
3139+
}
3140+
property_info.name = interned_name;
3141+
}
3142+
3143+
zend_hash_update(target_symbol_table, property_info.name, property_info.name_length+1, &property, sizeof(zval *), NULL);
3144+
31293145
property_info.flags = access_type;
31303146
property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
31313147

Zend/zend_builtin_functions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ ZEND_FUNCTION(define)
681681
zval_ptr_dtor(&val_free);
682682
}
683683
c.flags = case_sensitive; /* non persistent */
684-
c.name = zend_strndup(name, name_len);
684+
c.name = IS_INTERNED(name) ? name : zend_strndup(name, name_len);
685685
c.name_len = name_len+1;
686686
c.module_number = PHP_USER_CONSTANT;
687687
if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {

0 commit comments

Comments
 (0)