Permalink
Browse files

Added concept of interned strings. All strings constants known at com…

…pile time are allocated in a single copy and never changed.
  • Loading branch information...
Dmitry Stogov
Dmitry Stogov committed Apr 20, 2010
1 parent 94dd837 commit dd5c478be61a0ef94b54837cfa875c964356e14f
View
2 NEWS
@@ -4,6 +4,8 @@
- Upgraded bundled sqlite to version 3.6.23.1. (Ilia)
- Upgraded bundled PCRE to version 8.02. (Ilia)
+- Added concept of interned strings. All strings constants known at compile
+ time are allocated in a single copy and never changed. (Dmitry)
- Added an optimization which saves memory and emalloc/efree calls for empty
HashTables (Stas, Dmitry)
- Added Tokyo Cabinet abstract DB support to ext/dba. (Michael Maclean)
View
@@ -17,7 +17,7 @@ libZend_la_SOURCES=\
zend_objects_API.c zend_ts_hash.c zend_stream.c \
zend_default_classes.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c \
- zend_strtod.c zend_closures.c zend_float.c
+ zend_strtod.c zend_closures.c zend_float.c zend_string.c
libZend_la_LDFLAGS =
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
View
@@ -243,6 +243,10 @@ SOURCE=.\zend_stream.c
# End Source File
# Begin Source File
+SOURCE=.\zend_string.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_strtod.c
# End Source File
# Begin Source File
@@ -411,6 +415,10 @@ SOURCE=.\zend_stream.h
# End Source File
# Begin Source File
+SOURCE=.\zend_string.h
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_strtod.h
# End Source File
# Begin Source File
View
@@ -273,6 +273,10 @@ SOURCE=.\zend_stream.c
# End Source File
# Begin Source File
+SOURCE=.\zend_string.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_strtod.c
# End Source File
# Begin Source File
@@ -445,6 +449,10 @@ SOURCE=.\zend_stream.h
# End Source File
# Begin Source File
+SOURCE=.\zend_string.h
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_strtod.h
# End Source File
# Begin Source File
View
@@ -693,6 +693,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
EG(user_exception_handler) = NULL;
#endif
+ zend_interned_strings_init(TSRMLS_C);
zend_startup_builtin_functions(TSRMLS_C);
zend_register_standard_constants(TSRMLS_C);
zend_register_auto_global("GLOBALS", sizeof("GLOBALS") - 1, NULL TSRMLS_CC);
@@ -781,6 +782,8 @@ void zend_shutdown(TSRMLS_D) /* {{{ */
GLOBAL_CONSTANTS_TABLE = NULL;
#endif
zend_destroy_rsrc_list_dtors();
+
+ zend_interned_strings_dtor(TSRMLS_C);
}
/* }}} */
View
@@ -237,6 +237,7 @@ char *alloca ();
#include "zend_alloc.h"
#include "zend_types.h"
+#include "zend_string.h"
#ifdef HAVE_LIMITS_H
# include <limits.h>
@@ -599,8 +600,8 @@ END_EXTERN_C()
/* FIXME: Check if we can save if (ptr) too */
-#define STR_FREE(ptr) if (ptr) { efree(ptr); }
-#define STR_FREE_REL(ptr) if (ptr) { efree_rel(ptr); }
+#define STR_FREE(ptr) if (ptr && !IS_INTERNED(ptr)) { efree(ptr); }
+#define STR_FREE_REL(ptr) if (ptr && !IS_INTERNED(ptr)) { efree_rel(ptr); }
#define STR_EMPTY_ALLOC() estrndup("", sizeof("")-1)
View
@@ -1893,10 +1893,10 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
}
}
fname_len = strlen(ptr->fname);
- lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
+ lowercase_name = CG(new_interned_string)(zend_str_tolower_dup(ptr->fname, fname_len), fname_len + 1, 1 TSRMLS_CC);
if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)&reg_function) == FAILURE) {
unload=1;
- efree(lowercase_name);
+ str_efree(lowercase_name);
break;
}
if (scope) {
@@ -1938,7 +1938,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
}
ptr++;
count++;
- efree(lowercase_name);
+ str_efree(lowercase_name);
}
if (unload) { /* before unloading, display all remaining bad function in the module */
if (scope) {
@@ -2168,7 +2168,7 @@ int zend_next_free_module(void) /* {{{ */
static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */
{
zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
- char *lowercase_name = malloc(orig_class_entry->name_length + 1);
+ char *lowercase_name = emalloc(orig_class_entry->name_length + 1);
*class_entry = *orig_class_entry;
class_entry->type = ZEND_INTERNAL_CLASS;
@@ -2181,8 +2181,9 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class
}
zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length);
+ lowercase_name = CG(new_interned_string)(lowercase_name, class_entry->name_length + 1, 1 TSRMLS_CC);
zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL);
- free(lowercase_name);
+ str_efree(lowercase_name);
return class_entry;
}
/* }}} */
@@ -3070,6 +3071,7 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
{
zend_property_info property_info;
HashTable *target_symbol_table;
+ char *interned_name;
if (!(access_type & ZEND_ACC_PPP_MASK)) {
access_type |= ZEND_ACC_PUBLIC;
@@ -3097,7 +3099,6 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
int priv_name_length;
zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
- zend_hash_update(target_symbol_table, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL);
property_info.name = priv_name;
property_info.name_length = priv_name_length;
}
@@ -3107,7 +3108,6 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
int prot_name_length;
zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
- zend_hash_update(target_symbol_table, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
property_info.name = prot_name;
property_info.name_length = prot_name_length;
}
@@ -3121,11 +3121,27 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
zend_hash_del(target_symbol_table, prot_name, prot_name_length+1);
pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
}
- zend_hash_update(target_symbol_table, name, name_length+1, &property, sizeof(zval *), NULL);
- property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length);
+ if (IS_INTERNED(name)) {
+ property_info.name = (char*)name;
+ } else {
+ property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length);
+ }
property_info.name_length = name_length;
break;
}
+
+ interned_name = CG(new_interned_string)(property_info.name, property_info.name_length+1, 0 TSRMLS_CC);
+ if (interned_name != property_info.name) {
+ if (ce->type == ZEND_USER_CLASS) {
+ efree(property_info.name);
+ } else {
+ free(property_info.name);
+ }
+ property_info.name = interned_name;
+ }
+
+ zend_hash_update(target_symbol_table, property_info.name, property_info.name_length+1, &property, sizeof(zval *), NULL);
+
property_info.flags = access_type;
property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
@@ -681,7 +681,7 @@ ZEND_FUNCTION(define)
zval_ptr_dtor(&val_free);
}
c.flags = case_sensitive; /* non persistent */
- c.name = zend_strndup(name, name_len);
+ c.name = IS_INTERNED(name) ? name : zend_strndup(name, name_len);
c.name_len = name_len+1;
c.module_number = PHP_USER_CONSTANT;
if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
Oops, something went wrong.

0 comments on commit dd5c478

Please sign in to comment.