summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--Zend/Makefile.am2
-rw-r--r--Zend/Zend.dsp8
-rw-r--r--Zend/ZendTS.dsp8
-rw-r--r--Zend/zend.c3
-rw-r--r--Zend/zend.h5
-rw-r--r--Zend/zend_API.c34
-rw-r--r--Zend/zend_builtin_functions.c2
-rw-r--r--Zend/zend_compile.c65
-rw-r--r--Zend/zend_compile.h2
-rw-r--r--Zend/zend_constants.c12
-rw-r--r--Zend/zend_execute.c20
-rw-r--r--Zend/zend_execute_API.c6
-rw-r--r--Zend/zend_globals.h12
-rw-r--r--Zend/zend_hash.c71
-rw-r--r--Zend/zend_hash.h2
-rw-r--r--Zend/zend_language_scanner.l8
-rw-r--r--Zend/zend_opcode.c6
-rw-r--r--Zend/zend_operators.c72
-rw-r--r--Zend/zend_string.c229
-rw-r--r--Zend/zend_string.h67
-rw-r--r--Zend/zend_variables.c6
-rw-r--r--Zend/zend_vm_def.h22
-rw-r--r--Zend/zend_vm_execute.h274
-rw-r--r--configure.in2
-rw-r--r--ext/filter/sanitizing_filters.c12
-rw-r--r--ext/phar/phar.c44
-rw-r--r--ext/standard/array.c16
-rw-r--r--ext/standard/string.c16
-rw-r--r--win32/build/config.w322
30 files changed, 838 insertions, 192 deletions
diff --git a/NEWS b/NEWS
index 72b8ffbf69..7c302b58b8 100644
--- a/NEWS
+++ b/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)
diff --git a/Zend/Makefile.am b/Zend/Makefile.am
index 219d2d3fc9..04b51081bf 100644
--- a/Zend/Makefile.am
+++ b/Zend/Makefile.am
@@ -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@
diff --git a/Zend/Zend.dsp b/Zend/Zend.dsp
index 0a7ed77534..2a05c131e4 100644
--- a/Zend/Zend.dsp
+++ b/Zend/Zend.dsp
@@ -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
diff --git a/Zend/ZendTS.dsp b/Zend/ZendTS.dsp
index 2295b89ebb..c08cc77faa 100644
--- a/Zend/ZendTS.dsp
+++ b/Zend/ZendTS.dsp
@@ -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
diff --git a/Zend/zend.c b/Zend/zend.c
index 53bae4c95f..698992a6e6 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -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);
}
/* }}} */
diff --git a/Zend/zend.h b/Zend/zend.h
index fce65e0337..6348e5997c 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -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)
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index c08e43d35d..a7b73ea017 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -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);
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index ce4a1be893..7506401df2 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -681,7 +681,7 @@ repeat:
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) {
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 5a57f8e03f..339d92a9cb 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -73,7 +73,9 @@ ZEND_API zend_executor_globals executor_globals;
static void zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */
{
- property_info->name = estrndup(property_info->name, property_info->name_length);
+ if (!IS_INTERNED(property_info->name)) {
+ property_info->name = estrndup(property_info->name, property_info->name_length);
+ }
if (property_info->doc_comment) {
property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len);
}
@@ -83,14 +85,16 @@ static void zend_duplicate_property_info(zend_property_info *property_info) /* {
static void zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */
{
- property_info->name = zend_strndup(property_info->name, property_info->name_length);
+ if (!IS_INTERNED(property_info->name)) {
+ property_info->name = zend_strndup(property_info->name, property_info->name_length);
+ }
}
/* }}} */
static void zend_destroy_property_info(zend_property_info *property_info) /* {{{ */
{
- efree(property_info->name);
+ str_efree(property_info->name);
if (property_info->doc_comment) {
efree(property_info->doc_comment);
}
@@ -100,7 +104,7 @@ static void zend_destroy_property_info(zend_property_info *property_info) /* {{{
static void zend_destroy_property_info_internal(zend_property_info *property_info) /* {{{ */
{
- free(property_info->name);
+ str_free(property_info->name);
}
/* }}} */
@@ -292,17 +296,18 @@ static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
}
/* }}} */
-static int lookup_cv(zend_op_array *op_array, char* name, int name_len) /* {{{ */
+static int lookup_cv(zend_op_array *op_array, char* name, int name_len TSRMLS_DC) /* {{{ */
{
int i = 0;
ulong hash_value = zend_inline_hash_func(name, name_len+1);
while (i < op_array->last_var) {
- if (op_array->vars[i].hash_value == hash_value &&
- op_array->vars[i].name_len == name_len &&
- strcmp(op_array->vars[i].name, name) == 0) {
- efree(name);
- return i;
+ if (op_array->vars[i].name == name ||
+ (op_array->vars[i].hash_value == hash_value &&
+ op_array->vars[i].name_len == name_len &&
+ memcmp(op_array->vars[i].name, name, name_len) == 0)) {
+ str_efree(name);
+ return i;
}
i++;
}
@@ -312,7 +317,7 @@ static int lookup_cv(zend_op_array *op_array, char* name, int name_len) /* {{{ *
op_array->size_var += 16; /* FIXME */
op_array->vars = erealloc(op_array->vars, op_array->size_var*sizeof(zend_compiled_variable));
}
- op_array->vars[i].name = name; /* estrndup(name, name_len); */
+ op_array->vars[i].name = CG(new_interned_string)(name, name_len + 1, 1 TSRMLS_CC);
op_array->vars[i].name_len = name_len;
op_array->vars[i].hash_value = hash_value;
return i;
@@ -338,6 +343,13 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv) /* {{{ */
op_array->size_literal += 16; /* FIXME */
op_array->literals = (zend_literal*)erealloc(op_array->literals, op_array->size_literal * sizeof(zend_literal));
}
+ if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) {
+ zval *z = (zval*)zv;
+ TSRMLS_FETCH();
+
+ Z_STRVAL_P(z) =
+ CG(new_interned_string)(Z_STRVAL_P(zv), Z_STRLEN_P(zv) + 1, 1 TSRMLS_CC);
+ }
CONSTANT_EX(op_array, i) = *zv;
Z_SET_REFCOUNT(CONSTANT_EX(op_array, i), 2);
Z_SET_ISREF(CONSTANT_EX(op_array, i));
@@ -463,7 +475,8 @@ void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar
(CG(active_op_array)->last == 0 ||
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
result->op_type = IS_CV;
- result->u.op.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len);
+ result->u.op.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC);
+ varname->u.constant.value.str.val = CG(active_op_array)->vars[result->u.op.var].name;
result->EA = 0;
return;
}
@@ -1078,7 +1091,7 @@ void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS
this_var = opline_ptr->result.var;
if (CG(active_op_array)->this_var == -1) {
- CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(CONSTANT(opline_ptr->op1.constant)), Z_STRLEN(CONSTANT(opline_ptr->op1.constant)));
+ CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(CONSTANT(opline_ptr->op1.constant)), Z_STRLEN(CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC);
Z_TYPE(CONSTANT(opline_ptr->op1.constant)) = IS_NULL;
} else {
zend_del_literal(CG(active_op_array), opline_ptr->op1.constant);
@@ -1090,7 +1103,7 @@ void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS
variable->u.op.var = CG(active_op_array)->this_var;
}
} else if (CG(active_op_array)->this_var == -1) {
- CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1);
+ CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1 TSRMLS_CC);
}
}
@@ -1290,7 +1303,6 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
}
function_token->u.op_array = CG(active_op_array);
- lcname = zend_str_tolower_dup(name, name_len);
orig_interactive = CG(interactive);
CG(interactive) = 0;
@@ -1308,6 +1320,8 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
if (is_method) {
+ lcname = CG(new_interned_string)(zend_str_tolower_dup(name, name_len), name_len + 1, 1 TSRMLS_CC);
+
if (zend_hash_add(&CG(active_class_entry)->function_table, lcname, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
}
@@ -1413,7 +1427,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
free_alloca(class_lcname, use_heap);
}
- efree(lcname);
+ str_efree(lcname);
} else {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
zval key;
@@ -1426,9 +1440,10 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
zval_copy_ctor(&tmp.u.constant);
zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
op_array.function_name = Z_STRVAL(tmp.u.constant);
- efree(lcname);
name_len = Z_STRLEN(tmp.u.constant);
lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
+ } else {
+ lcname = zend_str_tolower_dup(name, name_len);
}
opline->opcode = ZEND_DECLARE_FUNCTION;
@@ -1596,7 +1611,7 @@ void zend_do_receive_arg(zend_uchar op, const znode *var, const znode *offset, c
}
CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
- cur_arg_info->name = estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len);
+ cur_arg_info->name = CG(new_interned_string)(estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len), varname->u.constant.value.str.len + 1, 1 TSRMLS_CC);
cur_arg_info->name_len = varname->u.constant.value.str.len;
cur_arg_info->array_type_hint = 0;
cur_arg_info->allow_null = 1;
@@ -1610,6 +1625,7 @@ void zend_do_receive_arg(zend_uchar op, const znode *var, const znode *offset, c
if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
zend_resolve_class_name(class_type, &opline->extended_value, 1 TSRMLS_CC);
}
+ class_type->u.constant.value.str.val = CG(new_interned_string)(class_type->u.constant.value.str.val, class_type->u.constant.value.str.len + 1, 1 TSRMLS_CC);
cur_arg_info->class_name = class_type->u.constant.value.str.val;
cur_arg_info->class_name_len = class_type->u.constant.value.str.len;
if (op == ZEND_RECV_INIT) {
@@ -1683,7 +1699,7 @@ zend_error(E_ERROR, "Internal error 1 ???");
lc_name = zend_str_tolower_dup(Z_STRVAL(CONSTANT(literal)), Z_STRLEN(CONSTANT(literal)));
ZVAL_STRINGL(&c, lc_name, Z_STRLEN(CONSTANT(literal)), 0);
lc_literal = zend_add_literal(CG(active_op_array), &c);
- Z_HASH_P(&CONSTANT(lc_literal)) = zend_hash_func(lc_name, Z_STRLEN(CONSTANT(literal))+1);
+ Z_HASH_P(&CONSTANT(lc_literal)) = zend_hash_func(Z_STRVAL(c), Z_STRLEN(c)+1);
if (literal + 1 != lc_literal) {
zend_error(E_ERROR, "Internal error 2 ???");
}
@@ -1710,7 +1726,7 @@ zend_error(E_ERROR, "Internal error 3 ???");
}
ZVAL_STRINGL(&c, lc_name, lc_len, 0);
lc_literal = zend_add_literal(CG(active_op_array), &c);
- Z_HASH_P(&CONSTANT(lc_literal)) = zend_hash_func(lc_name, lc_len+1);
+ Z_HASH_P(&CONSTANT(lc_literal)) = zend_hash_func(Z_STRVAL(c), Z_STRLEN(c)+1);
if (literal + 1 != lc_literal) {
zend_error(E_ERROR, "Internal error 4 ???");
}
@@ -2476,7 +2492,7 @@ void zend_do_try(znode *try_token TSRMLS_DC) /* {{{ */
}
/* }}} */
-void zend_do_begin_catch(znode *try_token, znode *class_name, const znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */
+void zend_do_begin_catch(znode *try_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */
{
long catch_op_number;
zend_op *opline;
@@ -2500,7 +2516,8 @@ void zend_do_begin_catch(znode *try_token, znode *class_name, const znode *catch
opline->opcode = ZEND_CATCH;
SET_NODE(opline->op1, &catch_class);
opline->op2_type = IS_CV;
- opline->op2.var = lookup_cv(CG(active_op_array), catch_var->u.constant.value.str.val, catch_var->u.constant.value.str.len);
+ opline->op2.var = lookup_cv(CG(active_op_array), catch_var->u.constant.value.str.val, catch_var->u.constant.value.str.len TSRMLS_CC);
+ catch_var->u.constant.value.str.val = CG(active_op_array)->vars[opline->op2.var].name;
opline->result.num = 0; /* 1 means it's the last catch in the block */
try_token->u.op.opline_num = catch_op_number;
@@ -3806,7 +3823,7 @@ void zend_do_declare_property(const znode *var_name, const znode *value, zend_ui
CG(doc_comment_len) = 0;
}
- zend_declare_property_ex(CG(active_class_entry), var_name->u.constant.value.str.val, var_name->u.constant.value.str.len, property, access_type, comment, comment_len TSRMLS_CC);
+ zend_declare_property_ex(CG(active_class_entry), CG(new_interned_string)(var_name->u.constant.value.str.val, var_name->u.constant.value.str.len + 1, 0 TSRMLS_CC), var_name->u.constant.value.str.len, property, access_type, comment, comment_len TSRMLS_CC);
efree(var_name->u.constant.value.str.val);
}
/* }}} */
@@ -3822,7 +3839,7 @@ void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_D
ALLOC_ZVAL(property);
*property = value->u.constant;
- if (zend_hash_add(&CG(active_class_entry)->constants_table, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL)==FAILURE) {
+ if (zend_hash_add(&CG(active_class_entry)->constants_table, CG(new_interned_string)(var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, 0 TSRMLS_CC), var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL)==FAILURE) {
FREE_ZVAL(property);
zend_error(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index b7185c7fcc..33e60aeb06 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -456,7 +456,7 @@ void zend_do_begin_lambda_function_declaration(znode *result, znode *function_to
void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC);
void zend_do_try(znode *try_token TSRMLS_DC);
-void zend_do_begin_catch(znode *try_token, znode *catch_class, const znode *catch_var, znode *first_catch TSRMLS_DC);
+void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, znode *first_catch TSRMLS_DC);
void zend_do_end_catch(const znode *try_token TSRMLS_DC);
void zend_do_throw(const znode *expr TSRMLS_DC);
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index 0543903e84..1743ffd2a8 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -32,13 +32,15 @@ void free_zend_constant(zend_constant *c)
if (!(c->flags & CONST_PERSISTENT)) {
zval_dtor(&c->value);
}
- free(c->name);
+ str_free(c->name);
}
void copy_zend_constant(zend_constant *c)
{
- c->name = zend_strndup(c->name, c->name_len - 1);
+ if (!IS_INTERNED(c->name)) {
+ c->name = zend_strndup(c->name, c->name_len - 1);
+ }
if (!(c->flags & CONST_PERSISTENT)) {
zval_copy_ctor(&c->value);
}
@@ -422,12 +424,14 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
/* keep in mind that c->name_len already contains the '\0' */
lowercase_name = estrndup(c->name, c->name_len-1);
zend_str_tolower(lowercase_name, c->name_len-1);
+ lowercase_name = CG(new_interned_string)(lowercase_name, c->name_len, 1 TSRMLS_CC);
name = lowercase_name;
} else {
char *slash = strrchr(c->name, '\\');
if(slash) {
lowercase_name = estrndup(c->name, c->name_len-1);
zend_str_tolower(lowercase_name, slash-c->name);
+ lowercase_name = CG(new_interned_string)(lowercase_name, c->name_len, 1 TSRMLS_CC);
name = lowercase_name;
} else {
name = c->name;
@@ -437,13 +441,13 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
if ((strncmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) ||
zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
zend_error(E_NOTICE,"Constant %s already defined", name);
- free(c->name);
+ str_free(c->name);
if (!(c->flags & CONST_PERSISTENT)) {
zval_dtor(&c->value);
}
ret = FAILURE;
}
- if (lowercase_name) {
+ if (lowercase_name && !IS_INTERNED(lowercase_name)) {
efree(lowercase_name);
}
return ret;
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index f941167ea9..7966ed144c 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -610,12 +610,24 @@ static inline int zend_assign_to_string_offset(const temp_variable *T, const zva
}
if (T->str_offset.offset >= Z_STRLEN_P(T->str_offset.str)) {
- Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1);
+ if (IS_INTERNED(Z_STRVAL_P(T->str_offset.str))) {
+ char *tmp = (char *) emalloc(T->str_offset.offset+1+1);
+
+ memcpy(tmp, Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1);
+ Z_STRVAL_P(T->str_offset.str) = tmp;
+ } else {
+ Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1);
+ }
memset(Z_STRVAL_P(T->str_offset.str) + Z_STRLEN_P(T->str_offset.str),
' ',
T->str_offset.offset - Z_STRLEN_P(T->str_offset.str));
Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset+1] = 0;
Z_STRLEN_P(T->str_offset.str) = T->str_offset.offset+1;
+ } else if (IS_INTERNED(Z_STRVAL_P(T->str_offset.str))) {
+ char *tmp = (char *) emalloc(Z_STRLEN_P(T->str_offset.str) + 1);
+
+ memcpy(tmp, Z_STRVAL_P(T->str_offset.str), Z_STRLEN_P(T->str_offset.str) + 1);
+ Z_STRVAL_P(T->str_offset.str) = tmp;
}
if (Z_TYPE_P(value) != IS_STRING) {
@@ -803,7 +815,11 @@ static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const zva
hval = Z_HASH_P(dim);
} else {
ZEND_HANDLE_NUMERIC_EX(offset_key, offset_key_length+1, index, goto num_index);
- hval = zend_hash_func(offset_key, offset_key_length+1);
+ if (IS_INTERNED(offset_key)) {
+ hval = INTERNED_HASH(offset_key);
+ } else {
+ hval = zend_hash_func(offset_key, offset_key_length+1);
+ }
}
fetch_string_dim:
if (zend_hash_quick_find(ht, offset_key, offset_key_length+1, hval, (void **) &retval) == FAILURE) {
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index d0ce7f1bf4..fd4fb928e4 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -525,7 +525,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
if (inline_change) {
colon = estrndup(colon, Z_STRLEN_P(p));
- efree(Z_STRVAL_P(p));
+ str_efree(Z_STRVAL_P(p));
Z_STRVAL_P(p) = colon;
} else {
Z_STRVAL_P(p) = colon + 1;
@@ -561,12 +561,12 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
if (fix_save) {
save--;
}
- if (inline_change) {
+ if (inline_change && !IS_INTERNED(save)) {
efree(save);
}
save = NULL;
}
- if (inline_change && save && save != actual) {
+ if (inline_change && save && save != actual && !IS_INTERNED(save)) {
efree(save);
}
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h
index 368e88ec39..19be67d1de 100644
--- a/Zend/zend_globals.h
+++ b/Zend/zend_globals.h
@@ -140,6 +140,18 @@ struct _zend_compiler_globals {
HashTable *labels;
zend_stack labels_stack;
+ /* interned strings */
+ char *interned_strings_start;
+ char *interned_strings_end;
+ char *interned_strings_top;
+ char *interned_strings_snapshot_top;
+
+ HashTable interned_strings;
+
+ char *(*new_interned_string)(char *str, int len, int free_src TSRMLS_DC);
+ void (*interned_strings_snapshot)(TSRMLS_D);
+ void (*interned_strings_restore)(TSRMLS_D);
+
#ifdef ZEND_MULTIBYTE
zend_encoding **script_encoding_list;
size_t script_encoding_list_size;
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 69b6bdc169..530afa7d34 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -20,6 +20,7 @@
/* $Id$ */
#include "zend.h"
+#include "zend_globals.h"
#define CONNECT_TO_BUCKET_DLLIST(element, list_head) \
(element)->pNext = (list_head); \
@@ -210,8 +211,8 @@ ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKe
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (p->arKey == arKey ||
+ ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
if (flag & HASH_ADD) {
return FAILURE;
}
@@ -232,16 +233,24 @@ ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKe
}
HANDLE_UNBLOCK_INTERRUPTIONS();
return SUCCESS;
- }
}
p = p->pNext;
}
- p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent);
- if (!p) {
- return FAILURE;
+ if (IS_INTERNED(arKey)) {
+ p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
+ if (!p) {
+ return FAILURE;
+ }
+ p->arKey = (char*)arKey;
+ } else {
+ p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent);
+ if (!p) {
+ return FAILURE;
+ }
+ p->arKey = (char*)(p + 1);
+ memcpy(p->arKey, arKey, nKeyLength);
}
- memcpy(p->arKey, arKey, nKeyLength);
p->nKeyLength = nKeyLength;
INIT_DATA(ht, p, pData, nDataSize);
p->h = h;
@@ -276,8 +285,8 @@ ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, ui
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (p->arKey == arKey ||
+ ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
if (flag & HASH_ADD) {
return FAILURE;
}
@@ -298,17 +307,25 @@ ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, ui
}
HANDLE_UNBLOCK_INTERRUPTIONS();
return SUCCESS;
- }
}
p = p->pNext;
}
- p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent);
- if (!p) {
- return FAILURE;
+ if (IS_INTERNED(arKey)) {
+ p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
+ if (!p) {
+ return FAILURE;
+ }
+ p->arKey = (char*)arKey;
+ } else {
+ p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent);
+ if (!p) {
+ return FAILURE;
+ }
+ p->arKey = (char*)(p + 1);
+ memcpy(p->arKey, arKey, nKeyLength);
}
- memcpy(p->arKey, arKey, nKeyLength);
p->nKeyLength = nKeyLength;
INIT_DATA(ht, p, pData, nDataSize);
p->h = h;
@@ -380,10 +397,11 @@ ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void
}
p = p->pNext;
}
- p = (Bucket *) pemalloc_rel(sizeof(Bucket) - 1, ht->persistent);
+ p = (Bucket *) pemalloc_rel(sizeof(Bucket), ht->persistent);
if (!p) {
return FAILURE;
}
+ p->arKey = NULL;
p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */
p->h = h;
INIT_DATA(ht, p, pData, nDataSize);
@@ -885,11 +903,10 @@ ZEND_API int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLen
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (p->arKey == arKey ||
+ ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
*pData = p->pData;
return SUCCESS;
- }
}
p = p->pNext;
}
@@ -912,11 +929,10 @@ ZEND_API int zend_hash_quick_find(const HashTable *ht, const char *arKey, uint n
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (p->arKey == arKey ||
+ ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
*pData = p->pData;
return SUCCESS;
- }
}
p = p->pNext;
}
@@ -937,10 +953,9 @@ ZEND_API int zend_hash_exists(const HashTable *ht, const char *arKey, uint nKeyL
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (p->arKey == arKey ||
+ ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
return 1;
- }
}
p = p->pNext;
}
@@ -963,10 +978,9 @@ ZEND_API int zend_hash_quick_exists(const HashTable *ht, const char *arKey, uint
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (p->arKey == arKey ||
+ ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
return 1;
- }
}
p = p->pNext;
}
@@ -1290,7 +1304,7 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
}
if (p->nKeyLength != str_length) {
- Bucket *q = (Bucket *) pemalloc(sizeof(Bucket) - 1 + str_length, ht->persistent);
+ Bucket *q = (Bucket *) pemalloc(sizeof(Bucket) + str_length, ht->persistent);
q->nKeyLength = str_length;
if (p->pData == &p->pDataPtr) {
@@ -1324,6 +1338,7 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
if (key_type == HASH_KEY_IS_LONG) {
p->h = num_index;
} else {
+ p->arKey = (char*)(p+1);
memcpy(p->arKey, str_index, str_length);
p->h = zend_inline_hash_func(str_index, str_length);
}
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index b26e0dbd6a..39a75fd1d4 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -60,7 +60,7 @@ typedef struct bucket {
struct bucket *pListLast;
struct bucket *pNext;
struct bucket *pLast;
- char arKey[1]; /* Must be last element */
+ char *arKey;
} Bucket;
typedef struct _hashtable {
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index a4faff3825..2857c87368 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -408,7 +408,13 @@ zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC)
ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC)
{
/* enforce two trailing NULLs for flex... */
- str->value.str.val = safe_erealloc(str->value.str.val, 1, str->value.str.len, ZEND_MMAP_AHEAD);
+ if (IS_INTERNED(str->value.str.val)) {
+ char *tmp = safe_emalloc(1, str->value.str.len, ZEND_MMAP_AHEAD);
+ memcpy(tmp, str->value.str.val, str->value.str.len + ZEND_MMAP_AHEAD);
+ str->value.str.val = tmp;
+ } else {
+ str->value.str.val = safe_erealloc(str->value.str.val, 1, str->value.str.len, ZEND_MMAP_AHEAD);
+ }
memset(str->value.str.val + str->value.str.len, 0, ZEND_MMAP_AHEAD);
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 9fdbd70870..9e9b2f5767 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -243,7 +243,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
i = op_array->last_var;
while (i > 0) {
i--;
- efree(op_array->vars[i].name);
+ str_efree(op_array->vars[i].name);
}
efree(op_array->vars);
}
@@ -275,8 +275,8 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
}
if (op_array->arg_info) {
for (i=0; i<op_array->num_args; i++) {
- efree((char*)op_array->arg_info[i].name);
- if (op_array->arg_info[i].class_name) {
+ str_efree((char*)op_array->arg_info[i].name);
+ if (op_array->arg_info[i].class_name && !IS_INTERNED(op_array->arg_info[i].class_name)) {
efree((char*)op_array->arg_info[i].class_name);
}
}
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 8af1edee50..abc7489dbf 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1177,11 +1177,18 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
/* must support result==op1 */
ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
- Z_STRLEN_P(result) = Z_STRLEN_P(op1) + 1;
- Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), Z_STRLEN_P(result)+1);
- Z_STRVAL_P(result)[Z_STRLEN_P(result) - 1] = (char) Z_LVAL_P(op2);
- Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
- Z_TYPE_P(result) = IS_STRING;
+ int length = Z_STRLEN_P(op1) + 1;
+ char *buf;
+
+ if (IS_INTERNED(Z_STRVAL_P(op1))) {
+ buf = (char *) emalloc(length + 1);
+ memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
+ } else {
+ buf = (char *) erealloc(Z_STRVAL_P(op1), length + 1);
+ }
+ buf[length - 1] = (char) Z_LVAL_P(op2);
+ buf[length] = 0;
+ ZVAL_STRINGL(result, buf, length, 0);
return SUCCESS;
}
/* }}} */
@@ -1190,12 +1197,17 @@ ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2)
ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
+ char *buf;
- Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), length+1);
- memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
- Z_STRVAL_P(result)[length] = 0;
- Z_STRLEN_P(result) = length;
- Z_TYPE_P(result) = IS_STRING;
+ if (IS_INTERNED(Z_STRVAL_P(op1))) {
+ buf = (char *) emalloc(length+1);
+ memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
+ } else {
+ buf = (char *) erealloc(Z_STRVAL_P(op1), length+1);
+ }
+ memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
+ buf[length] = 0;
+ ZVAL_STRINGL(result, buf, length, 0);
return SUCCESS;
}
/* }}} */
@@ -1224,7 +1236,7 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
if (use_copy2) {
op2 = &op2_copy;
}
- if (result==op1) { /* special case, perform operations on result */
+ if (result==op1 && !IS_INTERNED(Z_STRVAL_P(op1))) { /* special case, perform operations on result */
uint res_len = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
if (Z_STRLEN_P(result) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) {
@@ -1239,12 +1251,13 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
Z_STRVAL_P(result)[res_len]=0;
Z_STRLEN_P(result) = res_len;
} else {
- Z_STRLEN_P(result) = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
- Z_STRVAL_P(result) = (char *) emalloc(Z_STRLEN_P(result) + 1);
- memcpy(Z_STRVAL_P(result), Z_STRVAL_P(op1), Z_STRLEN_P(op1));
- memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
- Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
- Z_TYPE_P(result) = IS_STRING;
+ int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
+ char *buf = (char *) emalloc(length + 1);
+
+ memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
+ memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
+ buf[length] = 0;
+ ZVAL_STRINGL(result, buf, length, 0);
}
if (use_copy1) {
zval_dtor(op1);
@@ -1668,6 +1681,12 @@ static void increment_string(zval *str) /* {{{ */
return;
}
+ if (IS_INTERNED(s)) {
+ s = (char*) emalloc(Z_STRLEN_P(str) + 1);
+ memcpy(s, Z_STRVAL_P(str), Z_STRLEN_P(str) + 1);
+ Z_STRVAL_P(str) = s;
+ }
+
while (pos >= 0) {
ch = s[pos];
if (ch >= 'a' && ch <= 'z') {
@@ -1753,7 +1772,7 @@ ZEND_API int increment_function(zval *op1) /* {{{ */
switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
case IS_LONG:
- efree(Z_STRVAL_P(op1));
+ str_efree(Z_STRVAL_P(op1));
if (lval == LONG_MAX) {
/* switch to double */
double d = (double)lval;
@@ -1763,7 +1782,7 @@ ZEND_API int increment_function(zval *op1) /* {{{ */
}
break;
case IS_DOUBLE:
- efree(Z_STRVAL_P(op1));
+ str_efree(Z_STRVAL_P(op1));
ZVAL_DOUBLE(op1, dval+1);
break;
default:
@@ -1879,6 +1898,9 @@ ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint
{
int retval;
+ if (s1 == s2) {
+ return 0;
+ }
retval = memcmp(s1, s2, MIN(len1, len2));
if (!retval) {
return (len1 - len2);
@@ -1892,6 +1914,9 @@ ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint
{
int retval;
+ if (s1 == s2) {
+ return 0;
+ }
retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
if (!retval) {
return (MIN(length, len1) - MIN(length, len2));
@@ -1906,8 +1931,11 @@ ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, u
int len;
int c1, c2;
- len = MIN(len1, len2);
+ if (s1 == s2) {
+ return 0;
+ }
+ len = MIN(len1, len2);
while (len--) {
c1 = zend_tolower((int)*(unsigned char *)s1++);
c2 = zend_tolower((int)*(unsigned char *)s2++);
@@ -1925,8 +1953,10 @@ ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2,
int len;
int c1, c2;
+ if (s1 == s2) {
+ return 0;
+ }
len = MIN(length, MIN(len1, len2));
-
while (len--) {
c1 = zend_tolower((int)*(unsigned char *)s1++);
c2 = zend_tolower((int)*(unsigned char *)s2++);
diff --git a/Zend/zend_string.c b/Zend/zend_string.c
new file mode 100644
index 0000000000..098ad62713
--- /dev/null
+++ b/Zend/zend_string.c
@@ -0,0 +1,229 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2010 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: $ */
+
+#include "zend.h"
+#include "zend_globals.h"
+
+#ifndef ZEND_DEBUG_INTERNED_STRINGS
+# define ZEND_DEBUG_INTERNED_STRINGS 0
+#endif
+
+#if ZEND_DEBUG_INTERNED_STRINGS
+# include <sys/mman.h>
+#endif
+
+static char *zend_new_interned_string(char *str, int len, int free_src TSRMLS_DC);
+static void zend_interned_strings_snapshot(TSRMLS_D);
+static void zend_interned_strings_restore(TSRMLS_D);
+
+void zend_interned_strings_init(TSRMLS_D)
+{
+#ifndef ZTS
+ size_t size = 1024 * 1024;
+
+#if ZEND_DEBUG_INTERNED_STRINGS
+ CG(interned_strings_start) = valloc(size);
+#else
+ CG(interned_strings_start) = malloc(size);
+#endif
+
+ CG(interned_strings_top) = CG(interned_strings_start);
+ CG(interned_strings_snapshot_top) = CG(interned_strings_start);
+ CG(interned_strings_end) = CG(interned_strings_start) + size;
+
+ zend_hash_init(&CG(interned_strings), 0, NULL, NULL, 1);
+
+ CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
+ CG(interned_strings).arBuckets = (Bucket **) pecalloc(CG(interned_strings).nTableSize, sizeof(Bucket *), CG(interned_strings).persistent);
+
+#if ZEND_DEBUG_INTERNED_STRINGS
+ mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
+#endif
+
+#endif
+
+ CG(new_interned_string) = zend_new_interned_string;
+ CG(interned_strings_snapshot) = zend_interned_strings_snapshot;
+ CG(interned_strings_restore) = zend_interned_strings_restore;
+}
+
+void zend_interned_strings_dtor(TSRMLS_D)
+{
+#ifndef ZTS
+#if ZEND_DEBUG_INTERNED_STRINGS
+ mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ);
+#endif
+ free(CG(interned_strings).arBuckets);
+ free(CG(interned_strings_start));
+#endif
+}
+
+static char *zend_new_interned_string(char *arKey, int nKeyLength, int free_src TSRMLS_DC)
+{
+#ifndef ZTS
+ ulong h;
+ uint nIndex;
+ Bucket *p;
+
+ if (IS_INTERNED(arKey)) {
+ return arKey;
+ }
+
+ h = zend_inline_hash_func(arKey, nKeyLength);
+ nIndex = h & CG(interned_strings).nTableMask;
+ p = CG(interned_strings).arBuckets[nIndex];
+ while (p != NULL) {
+ if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
+ if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (free_src) {
+ efree(arKey);
+ }
+ return p->arKey;
+ }
+ }
+ p = p->pNext;
+ }
+
+ if (CG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength) >=
+ CG(interned_strings_end)) {
+ /* no memory */
+ return arKey;
+ }
+
+ p = (Bucket *) CG(interned_strings_top);
+ CG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength);
+
+#if ZEND_DEBUG_INTERNED_STRINGS
+ mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ | PROT_WRITE);
+#endif
+
+ p->arKey = (char*)(p+1);
+ memcpy(p->arKey, arKey, nKeyLength);
+ if (free_src) {
+ efree(arKey);
+ }
+ p->nKeyLength = nKeyLength;
+ p->h = h;
+ p->pData = &p->pDataPtr;
+ p->pDataPtr = p;
+
+ p->pNext = CG(interned_strings).arBuckets[nIndex];
+ p->pLast = NULL;
+ if (p->pNext) {
+ p->pNext->pLast = p;
+ }
+
+ HANDLE_BLOCK_INTERRUPTIONS();
+
+ p->pListLast = CG(interned_strings).pListTail;
+ CG(interned_strings).pListTail = p;
+ p->pListNext = NULL;
+ if (p->pListLast != NULL) {
+ p->pListLast->pListNext = p;
+ }
+ if (!CG(interned_strings).pListHead) {
+ CG(interned_strings).pListHead = p;
+ }
+
+ CG(interned_strings).arBuckets[nIndex] = p;
+
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+
+ CG(interned_strings).nNumOfElements++;
+
+ if (CG(interned_strings).nNumOfElements > CG(interned_strings).nTableSize) {
+ if ((CG(interned_strings).nTableSize << 1) > 0) { /* Let's double the table size */
+ Bucket **t = (Bucket **) perealloc_recoverable(CG(interned_strings).arBuckets, (CG(interned_strings).nTableSize << 1) * sizeof(Bucket *), CG(interned_strings).persistent);
+
+ if (t) {
+ HANDLE_BLOCK_INTERRUPTIONS();
+ CG(interned_strings).arBuckets = t;
+ CG(interned_strings).nTableSize = (CG(interned_strings).nTableSize << 1);
+ CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
+ zend_hash_rehash(&CG(interned_strings));
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+ }
+ }
+ }
+
+#if ZEND_DEBUG_INTERNED_STRINGS
+ mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
+#endif
+
+ return p->arKey;
+#else
+ return arKey;
+#endif
+}
+
+static void zend_interned_strings_snapshot(TSRMLS_D)
+{
+ CG(interned_strings_snapshot_top) = CG(interned_strings_top);
+}
+
+static void zend_interned_strings_restore(TSRMLS_D)
+{
+#ifndef ZTS
+ Bucket *p;
+ int i;
+#endif
+
+ CG(interned_strings_top) = CG(interned_strings_snapshot_top);
+
+#ifndef ZTS
+#if ZEND_DEBUG_INTERNED_STRINGS
+ mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ);
+#endif
+
+ for (i = 0; i < CG(interned_strings).nTableSize; i++) {
+ p = CG(interned_strings).arBuckets[i];
+ while (p && p->arKey > CG(interned_strings_top)) {
+ CG(interned_strings).nNumOfElements--;
+ if (p->pListLast != NULL) {
+ p->pListLast->pListNext = p->pListNext;
+ } else {
+ CG(interned_strings).pListHead = p->pListNext;
+ }
+ if (p->pListNext != NULL) {
+ p->pListNext->pListLast = p->pListLast;
+ } else {
+ CG(interned_strings).pListTail = p->pListLast;
+ }
+ p = p->pNext;
+ }
+ if (p) {
+ p->pLast = NULL;
+ }
+ CG(interned_strings).arBuckets[i] = p;
+ }
+
+#if ZEND_DEBUG_INTERNED_STRINGS
+ mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
+#endif
+#endif
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/Zend/zend_string.h b/Zend/zend_string.h
new file mode 100644
index 0000000000..158efceeb8
--- /dev/null
+++ b/Zend/zend_string.h
@@ -0,0 +1,67 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2010 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: $ */
+
+#ifndef ZEND_STRING_H
+#define ZEND_STRING_H
+
+#include "zend.h"
+
+void zend_interned_strings_init(TSRMLS_D);
+void zend_interned_strings_dtor(TSRMLS_D);
+
+#ifndef ZTS
+
+#define IS_INTERNED(s) \
+ (((s) >= CG(interned_strings_start)) && ((s) < CG(interned_strings_end)))
+
+#else
+
+#define IS_INTERNED(s) \
+ (0)
+
+#endif
+
+#define INTERNED_LEN(s) \
+ (((Bucket*)(((char*)(s))-sizeof(Bucket)))->nKeyLength)
+
+#define INTERNED_HASH(s) \
+ (((Bucket*)(((char*)(s))-sizeof(Bucket)))->h)
+
+#define str_efree(s) do { \
+ if (!IS_INTERNED(s)) { \
+ efree(s); \
+ } \
+ } while (0)
+
+#define str_free(s) do { \
+ if (!IS_INTERNED(s)) { \
+ free(s); \
+ } \
+ } while (0)
+
+#endif /* ZEND_STRING_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c
index dce98ba22c..47f2462761 100644
--- a/Zend/zend_variables.c
+++ b/Zend/zend_variables.c
@@ -77,7 +77,7 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
case IS_STRING:
case IS_CONSTANT:
CHECK_ZVAL_STRING_REL(zvalue);
- free(zvalue->value.str.val);
+ str_free(zvalue->value.str.val);
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
@@ -117,7 +117,9 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
case IS_CONSTANT:
case IS_STRING:
CHECK_ZVAL_STRING_REL(zvalue);
- zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val, zvalue->value.str.len);
+ if (!IS_INTERNED(zvalue->value.str.val)) {
+ zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val, zvalue->value.str.len);
+ }
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY: {
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 0fe828d3dd..735c9daaa8 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -951,6 +951,8 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, ANY, int type
*/
if (OP1_TYPE == IS_CONST) {
hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
} else {
hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
}
@@ -3115,7 +3117,11 @@ ZEND_VM_C_LABEL(num_index):
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, ZEND_VM_C_GOTO(num_index));
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -3459,7 +3465,11 @@ ZEND_VM_C_LABEL(num_index_dim):
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, ZEND_VM_C_GOTO(num_index_dim));
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -3967,7 +3977,11 @@ ZEND_VM_C_LABEL(num_index_prop):
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, ZEND_VM_C_GOTO(num_index_prop));
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
@@ -4419,7 +4433,7 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
zval_copy_ctor(&c.value);
}
c.flags = CONST_CS; /* non persistent, case sensetive */
- c.name = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+ c.name = IS_INTERNED(Z_STRVAL_P(name)) ? Z_STRVAL_P(name) : zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
c.name_len = Z_STRLEN_P(name)+1;
c.module_number = PHP_USER_CONSTANT;
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 26434e5c6c..3650dfac24 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -1367,6 +1367,8 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST(int type, ZEND
*/
if (IS_CONST == IS_CONST) {
hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
} else {
hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
}
@@ -2889,7 +2891,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -2951,7 +2957,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
zval_copy_ctor(&c.value);
}
c.flags = CONST_CS; /* non persistent, case sensetive */
- c.name = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+ c.name = IS_INTERNED(Z_STRVAL_P(name)) ? Z_STRVAL_P(name) : zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
c.name_len = Z_STRLEN_P(name)+1;
c.module_number = PHP_USER_CONSTANT;
@@ -3399,7 +3405,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -3875,7 +3885,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -4075,7 +4089,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -4565,7 +4583,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -4685,6 +4707,8 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP(int type, ZEND_O
*/
if (IS_TMP_VAR == IS_CONST) {
hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
} else {
hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
}
@@ -6175,7 +6199,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -6651,7 +6679,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -7127,7 +7159,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -7230,7 +7266,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -7703,7 +7743,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -7981,6 +8025,8 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR(int type, ZEND_O
*/
if (IS_VAR == IS_CONST) {
hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
} else {
hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
}
@@ -10759,7 +10805,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -10834,7 +10884,11 @@ num_index_dim:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -10974,7 +11028,11 @@ num_index_prop:
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop);
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
@@ -12528,7 +12586,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -12603,7 +12665,11 @@ num_index_dim:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -12743,7 +12809,11 @@ num_index_prop:
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop);
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
@@ -14348,7 +14418,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -14423,7 +14497,11 @@ num_index_dim:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -14563,7 +14641,11 @@ num_index_prop:
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop);
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
@@ -15230,7 +15312,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -16764,7 +16850,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -16839,7 +16929,11 @@ num_index_dim:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -16979,7 +17073,11 @@ num_index_prop:
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop);
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
@@ -18041,7 +18139,11 @@ num_index_dim:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -18179,7 +18281,11 @@ num_index_prop:
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop);
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
@@ -19108,7 +19214,11 @@ num_index_dim:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -19246,7 +19356,11 @@ num_index_prop:
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop);
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
@@ -20175,7 +20289,11 @@ num_index_dim:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -20313,7 +20431,11 @@ num_index_prop:
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop);
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
@@ -21501,7 +21623,11 @@ num_index_dim:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -21639,7 +21765,11 @@ num_index_prop:
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop);
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
@@ -21975,6 +22105,8 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV(int type, ZEND_OP
*/
if (IS_CV == IS_CONST) {
hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
} else {
hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
}
@@ -24436,7 +24568,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -24511,7 +24647,11 @@ num_index_dim:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -24649,7 +24789,11 @@ num_index_prop:
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop);
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
@@ -26096,7 +26240,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -26171,7 +26319,11 @@ num_index_dim:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -26309,7 +26461,11 @@ num_index_prop:
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop);
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
@@ -27806,7 +27962,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -27881,7 +28041,11 @@ num_index_dim:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -28019,7 +28183,11 @@ num_index_prop:
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop);
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
@@ -28585,7 +28753,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -30013,7 +30185,11 @@ num_index:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
@@ -30088,7 +30264,11 @@ num_index_dim:
hval = Z_HASH_P(offset);
} else {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim);
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS &&
ht == &EG(symbol_table)) {
@@ -30226,7 +30406,11 @@ num_index_prop:
if (!prop_dim) {
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop);
}
- hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
}
if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
isset = 1;
diff --git a/configure.in b/configure.in
index 230d93fbc6..d88cf11897 100644
--- a/configure.in
+++ b/configure.in
@@ -1424,7 +1424,7 @@ PHP_ADD_SOURCES(Zend, \
zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
- zend_closures.c zend_float.c)
+ zend_closures.c zend_float.c zend_string.c)
if test -r "$abs_srcdir/Zend/zend_objects.c"; then
PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_default_classes.c)
diff --git a/ext/filter/sanitizing_filters.c b/ext/filter/sanitizing_filters.c
index c44d7a8e55..d54ced2f4b 100644
--- a/ext/filter/sanitizing_filters.c
+++ b/ext/filter/sanitizing_filters.c
@@ -51,7 +51,7 @@ static void php_filter_encode_html(zval *value, const unsigned char *chars)
}
smart_str_0(&str);
- efree(Z_STRVAL_P(value));
+ str_efree(Z_STRVAL_P(value));
Z_STRVAL_P(value) = str.c;
Z_STRLEN_P(value) = str.len;
}
@@ -102,7 +102,7 @@ static void php_filter_encode_url(zval *value, const unsigned char* chars, const
s++;
}
*p = '\0';
- efree(Z_STRVAL_P(value));
+ str_efree(Z_STRVAL_P(value));
Z_STRVAL_P(value) = (char *)str;
Z_STRLEN_P(value) = p - str;
}
@@ -131,7 +131,7 @@ static void php_filter_strip(zval *value, long flags)
}
/* update zval string data */
buf[c] = '\0';
- efree(Z_STRVAL_P(value));
+ str_efree(Z_STRVAL_P(value));
Z_STRVAL_P(value) = (char *)buf;
Z_STRLEN_P(value) = c;
}
@@ -169,7 +169,7 @@ static void filter_map_apply(zval *value, filter_map *map)
}
/* update zval string data */
buf[c] = '\0';
- efree(Z_STRVAL_P(value));
+ str_efree(Z_STRVAL_P(value));
Z_STRVAL_P(value) = (char *)buf;
Z_STRLEN_P(value) = c;
}
@@ -254,7 +254,7 @@ void php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL)
quotes = ENT_NOQUOTES;
}
buf = php_escape_html_entities_ex(Z_STRVAL_P(value), Z_STRLEN_P(value), &len, 1, quotes, SG(default_charset), 0 TSRMLS_CC);
- efree(Z_STRVAL_P(value));
+ str_efree(Z_STRVAL_P(value));
Z_STRVAL_P(value) = buf;
Z_STRLEN_P(value) = len;
}
@@ -365,7 +365,7 @@ void php_filter_magic_quotes(PHP_INPUT_FILTER_PARAM_DECL)
/* just call php_addslashes quotes */
buf = php_addslashes(Z_STRVAL_P(value), Z_STRLEN_P(value), &len, 0 TSRMLS_CC);
- efree(Z_STRVAL_P(value));
+ str_efree(Z_STRVAL_P(value));
Z_STRVAL_P(value) = buf;
Z_STRLEN_P(value) = len;
}
diff --git a/ext/phar/phar.c b/ext/phar/phar.c
index 52179b1246..745eee09da 100644
--- a/ext/phar/phar.c
+++ b/ext/phar/phar.c
@@ -1736,31 +1736,30 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
static int phar_analyze_path(const char *fname, const char *ext, int ext_len, int for_create TSRMLS_DC) /* {{{ */
{
php_stream_statbuf ssb;
- char *realpath, old, *a = (char *)(ext + ext_len);
+ char *realpath;
+ char *filename = estrndup(fname, (ext - fname) + ext_len);
- old = *a;
- *a = '\0';
-
- if ((realpath = expand_filepath(fname, NULL TSRMLS_CC))) {
+ if ((realpath = expand_filepath(filename, NULL TSRMLS_CC))) {
#ifdef PHP_WIN32
phar_unixify_path_separators(realpath, strlen(realpath));
#endif
if (zend_hash_exists(&(PHAR_GLOBALS->phar_fname_map), realpath, strlen(realpath))) {
- *a = old;
efree(realpath);
+ efree(filename);
return SUCCESS;
}
if (PHAR_G(manifest_cached) && zend_hash_exists(&cached_phars, realpath, strlen(realpath))) {
- *a = old;
efree(realpath);
+ efree(filename);
return SUCCESS;
}
efree(realpath);
}
- if (SUCCESS == php_stream_stat_path((char *) fname, &ssb)) {
- *a = old;
+ if (SUCCESS == php_stream_stat_path((char *) filename, &ssb)) {
+
+ efree(filename);
if (ssb.sb.st_mode & S_IFDIR) {
return FAILURE;
@@ -1775,57 +1774,56 @@ static int phar_analyze_path(const char *fname, const char *ext, int ext_len, in
char *slash;
if (!for_create) {
- *a = old;
+ efree(filename);
return FAILURE;
}
- slash = (char *) strrchr(fname, '/');
- *a = old;
+ slash = (char *) strrchr(filename, '/');
if (slash) {
- old = *slash;
*slash = '\0';
}
- if (SUCCESS != php_stream_stat_path((char *) fname, &ssb)) {
- if (slash) {
- *slash = old;
- } else {
- if (!(realpath = expand_filepath(fname, NULL TSRMLS_CC))) {
+ if (SUCCESS != php_stream_stat_path((char *) filename, &ssb)) {
+ if (!slash) {
+ if (!(realpath = expand_filepath(filename, NULL TSRMLS_CC))) {
+ efree(filename);
return FAILURE;
}
#ifdef PHP_WIN32
phar_unixify_path_separators(realpath, strlen(realpath));
#endif
- a = strstr(realpath, fname) + ((ext - fname) + ext_len);
- *a = '\0';
+ slash = strstr(realpath, filename) + ((ext - fname) + ext_len);
+ *slash = '\0';
slash = strrchr(realpath, '/');
if (slash) {
*slash = '\0';
} else {
efree(realpath);
+ efree(filename);
return FAILURE;
}
if (SUCCESS != php_stream_stat_path(realpath, &ssb)) {
efree(realpath);
+ efree(filename);
return FAILURE;
}
efree(realpath);
if (ssb.sb.st_mode & S_IFDIR) {
+ efree(filename);
return SUCCESS;
}
}
+ efree(filename);
return FAILURE;
}
- if (slash) {
- *slash = old;
- }
+ efree(filename);
if (ssb.sb.st_mode & S_IFDIR) {
return SUCCESS;
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 1988ea3a44..cd9b398355 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -1653,24 +1653,28 @@ PHP_FUNCTION(range)
high = (unsigned char *)Z_STRVAL_P(zhigh);
if (*low > *high) { /* Negative Steps */
+ unsigned char ch = *low;
+
if (lstep <= 0) {
err = 1;
goto err;
}
- for (; *low >= *high; (*low) -= (unsigned int)lstep) {
- add_next_index_stringl(return_value, (const char *)low, 1, 1);
- if (((signed int)*low - lstep) < 0) {
+ for (; ch >= *high; ch -= (unsigned int)lstep) {
+ add_next_index_stringl(return_value, (const char *)&ch, 1, 1);
+ if (((signed int)ch - lstep) < 0) {
break;
}
}
} else if (*high > *low) { /* Positive Steps */
+ unsigned char ch = *low;
+
if (lstep <= 0) {
err = 1;
goto err;
}
- for (; *low <= *high; (*low) += (unsigned int)lstep) {
- add_next_index_stringl(return_value, (const char *)low, 1, 1);
- if (((signed int)*low + lstep) > 255) {
+ for (; ch <= *high; ch += (unsigned int)lstep) {
+ add_next_index_stringl(return_value, (const char *)&ch, 1, 1);
+ if (((signed int)ch + lstep) > 255) {
break;
}
}
diff --git a/ext/standard/string.c b/ext/standard/string.c
index 88b8099683..1ffbaa9663 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -3589,7 +3589,7 @@ static void php_str_replace_in_subject(zval *search, zval *replace, zval **subje
replace_value, replace_len, &Z_STRLEN(temp_result), case_sensitivity, replace_count);
}
- efree(Z_STRVAL_P(result));
+ str_efree(Z_STRVAL_P(result));
Z_STRVAL_P(result) = Z_STRVAL(temp_result);
Z_STRLEN_P(result) = Z_STRLEN(temp_result);
@@ -4244,6 +4244,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow,
char *tbuf, *buf, *p, *tp, *rp, c, lc;
int br, i=0, depth=0, in_q = 0;
int state = 0, pos;
+ char *allow_free;
if (stateptr)
state = *stateptr;
@@ -4255,7 +4256,12 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow,
rp = rbuf;
br = 0;
if (allow) {
- php_strtolower(allow, allow_len);
+ if (IS_INTERNED(allow)) {
+ allow_free = allow = zend_str_tolower_dup(allow, allow_len);
+ } else {
+ allow_free = NULL;
+ php_strtolower(allow, allow_len);
+ }
tbuf = emalloc(PHP_TAG_BUF_SIZE + 1);
tp = tbuf;
} else {
@@ -4494,8 +4500,12 @@ reg_char:
*rp = '\0';
}
efree(buf);
- if (allow)
+ if (allow) {
efree(tbuf);
+ if (allow_free) {
+ efree(allow_free);
+ }
+ }
if (stateptr)
*stateptr = state;
diff --git a/win32/build/config.w32 b/win32/build/config.w32
index c52ce01737..d876566e14 100644
--- a/win32/build/config.w32
+++ b/win32/build/config.w32
@@ -325,7 +325,7 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \
zend_stream.c zend_iterators.c zend_interfaces.c zend_objects.c \
zend_object_handlers.c zend_objects_API.c \
zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c \
- zend_float.c");
+ zend_float.c zend_string.c");
if (VCVERS == 1200) {
AC_DEFINE('ZEND_DVAL_TO_LVAL_CAST_OK', 1);