]> granicus.if.org Git - php/commitdiff
Interned strings unification for TS/NTS
authorAnatol Belski <ab@php.net>
Sat, 4 Mar 2017 09:39:13 +0000 (10:39 +0100)
committerAnatol Belski <ab@php.net>
Sat, 4 Mar 2017 09:39:13 +0000 (10:39 +0100)
Hereby, interned strings are supported in thread safe PHP. The patch
implements two types of interned strings

- interning per process, strings are not freed till process end
- interning per request, strings are freed at request end

There is no runtime interning.

With Opcache, all the permanent iterned strings are copied into SHM on
startup, additional copying into SHM might happen on demand.

28 files changed:
TSRM/TSRM.c
TSRM/TSRM.h
Zend/zend.c
Zend/zend_API.c
Zend/zend_builtin_functions.c
Zend/zend_closures.c
Zend/zend_compile.c
Zend/zend_constants.c
Zend/zend_exceptions.c
Zend/zend_execute.c
Zend/zend_execute_API.c
Zend/zend_globals.h
Zend/zend_ini.c
Zend/zend_language_parser.y
Zend/zend_object_handlers.c
Zend/zend_operators.c
Zend/zend_string.c
Zend/zend_string.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/opcache/ZendAccelerator.c
ext/opcache/zend_persist.c
ext/opcache/zend_persist_calc.c
ext/standard/array.c
ext/standard/string.c
main/main.c
main/streams/streams.c
sapi/phpdbg/phpdbg.c

index 6669df6d43c22d1dd7d86b5a5f57667d5db96659..2c7a40a2de4503b36416ba48e68fbe6032bea56d 100644 (file)
@@ -55,8 +55,9 @@ static int                                    resource_types_table_size;
 static MUTEX_T tsmm_mutex;     /* thread-safe memory manager mutex */
 
 /* New thread handlers */
-static tsrm_thread_begin_func_t tsrm_new_thread_begin_handler;
-static tsrm_thread_end_func_t tsrm_new_thread_end_handler;
+static tsrm_thread_begin_func_t tsrm_new_thread_begin_handler = NULL;
+static tsrm_thread_end_func_t tsrm_new_thread_end_handler = NULL;
+static tsrm_shutdown_func_t tsrm_shutdown_handler = NULL;
 
 /* Debug support */
 int tsrm_error(int level, const char *format, ...);
@@ -120,6 +121,8 @@ static int32 tls_key;
 # warning tsrm_set_interpreter_context is probably broken on this platform
 #endif
 
+TSRM_TLS uint8_t in_main_thread = 0;
+
 /* Startup TSRM (call once for the entire process) */
 TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename)
 {
@@ -136,6 +139,9 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
        tls_key = tls_allocate();
 #endif
 
+       /* ensure singleton */
+       in_main_thread = 1;
+
        tsrm_error_file = stderr;
        tsrm_error_set(debug_level, debug_filename);
        tsrm_tls_table_size = expected_threads;
@@ -158,8 +164,6 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
 
        tsmm_mutex = tsrm_mutex_alloc();
 
-       tsrm_new_thread_begin_handler = tsrm_new_thread_end_handler = NULL;
-
        TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Started up TSRM, %d expected threads, %d expected resources", expected_threads, expected_resources));
        return 1;
 }
@@ -170,6 +174,11 @@ TSRM_API void tsrm_shutdown(void)
 {
        int i;
 
+       if (!in_main_thread) {
+               /* ensure singleton */
+               return;
+       }
+
        if (tsrm_tls_table) {
                for (i=0; i<tsrm_tls_table_size; i++) {
                        tsrm_tls_entry *p = tsrm_tls_table[i], *next_p;
@@ -212,6 +221,12 @@ TSRM_API void tsrm_shutdown(void)
 #elif defined(TSRM_WIN32)
        TlsFree(tls_key);
 #endif
+       if (tsrm_shutdown_handler) {
+               tsrm_shutdown_handler();
+       }
+       tsrm_new_thread_begin_handler = NULL;
+       tsrm_new_thread_end_handler = NULL;
+       tsrm_shutdown_handler = NULL;
 }
 
 
@@ -740,6 +755,14 @@ TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread
 }
 
 
+TSRM_API void *tsrm_set_shutdown_handler(tsrm_shutdown_func_t shutdown_handler)
+{
+       void *retval = (void *) tsrm_shutdown_handler;
+
+       tsrm_shutdown_handler = shutdown_handler;
+       return retval;
+}
+
 
 /*
  * Debug support
index f9bb241050112a41e9491b4c2f1b928dbfc6995d..2ffcbfee76c7415fb86aae88de99d06a124cb0bf 100644 (file)
@@ -128,6 +128,7 @@ TSRM_API void ts_free_id(ts_rsrc_id id);
 
 typedef void (*tsrm_thread_begin_func_t)(THREAD_T thread_id);
 typedef void (*tsrm_thread_end_func_t)(THREAD_T thread_id);
+typedef void (*tsrm_shutdown_func_t)(void);
 
 
 TSRM_API int tsrm_error(int level, const char *format, ...);
@@ -145,6 +146,7 @@ TSRM_API int tsrm_sigmask(int how, const sigset_t *set, sigset_t *oldset);
 
 TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler);
 TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler);
+TSRM_API void *tsrm_set_shutdown_handler(tsrm_shutdown_func_t shutdown_handler);
 
 /* these 3 APIs should only be used by people that fully understand the threading model
  * used by PHP/Zend and the selected SAPI. */
index f6da5735d404b6e100431d730db05e7a13cdfebe..f99a580fa1e139eb6ef8897741d46a8409d617c0 100644 (file)
@@ -580,12 +580,6 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{
                compiler_globals->static_members_table = NULL;
        }
        compiler_globals->script_encoding_list = NULL;
-
-       compiler_globals->empty_string = zend_zts_interned_string_init("", sizeof("")-1);
-
-       memset(compiler_globals->one_char_string, 0, sizeof(compiler_globals->one_char_string));
-
-       zend_known_interned_strings_init(&compiler_globals->known_strings, &compiler_globals->known_strings_count);
 }
 /* }}} */
 
@@ -610,11 +604,6 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals) /* {{
                pefree((char*)compiler_globals->script_encoding_list, 1);
        }
        compiler_globals->last_static_member = 0;
-
-       zend_zts_interned_string_free(&compiler_globals->empty_string);
-
-       compiler_globals->known_strings = NULL;
-       compiler_globals->known_strings_count = 0;
 }
 /* }}} */
 
@@ -856,6 +845,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) /
 
 #ifdef ZTS
        tsrm_set_new_thread_end_handler(zend_new_thread_end_handler);
+       tsrm_set_shutdown_handler(zend_interned_strings_dtor);
 #endif
 
        return SUCCESS;
@@ -967,7 +957,9 @@ void zend_shutdown(void) /* {{{ */
 #endif
        zend_destroy_rsrc_list_dtors();
 
+#ifndef ZTS
        zend_interned_strings_dtor();
+#endif
 }
 /* }}} */
 
index bbea611697183449e479d123f9e4012cf4fddee9..f48c7746340f7fe2553d9b53fa9d91d793dc9572 100644 (file)
@@ -2019,6 +2019,7 @@ ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module) /
        lcname = zend_string_alloc(name_len, 1);
        zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len);
 
+       lcname = zend_new_interned_string(lcname);
        if ((module_ptr = zend_hash_add_mem(&module_registry, lcname, module, sizeof(zend_module_entry))) == NULL) {
                zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);
                zend_string_release(lcname);
@@ -3816,6 +3817,9 @@ ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name,
        int ret;
 
        zend_string *key = zend_string_init(name, name_length, ce->type & ZEND_INTERNAL_CLASS);
+       if (ce->type == ZEND_INTERNAL_CLASS) {
+               key = zend_new_interned_string(key);
+       }
        ret = zend_declare_class_constant_ex(ce, key, value, ZEND_ACC_PUBLIC, NULL);
        zend_string_release(key);
        return ret;
index 91bf0ee7b0ea1db4da0ea53eaffbe8a7469db66e..55d1209ae0e8d5850d0d3d05ed32323a864b66cb 100644 (file)
@@ -763,7 +763,7 @@ ZEND_FUNCTION(each)
                if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
        }
        zend_hash_index_add_new(Z_ARRVAL_P(return_value), 1, entry);
-       zend_hash_add_new(Z_ARRVAL_P(return_value), CG(known_strings)[ZEND_STR_VALUE], entry);
+       zend_hash_add_new(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_VALUE), entry);
 
        /* add the key elements */
        if (zend_hash_get_current_key(target_hash, &key, &num_key) == HASH_KEY_IS_STRING) {
@@ -773,7 +773,7 @@ ZEND_FUNCTION(each)
                ZVAL_LONG(&tmp, num_key);
        }
        zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp);
-       zend_hash_add_new(Z_ARRVAL_P(return_value), CG(known_strings)[ZEND_STR_KEY], &tmp);
+       zend_hash_add_new(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_KEY), &tmp);
        zend_hash_move_forward(target_hash);
 }
 /* }}} */
@@ -797,7 +797,7 @@ ZEND_FUNCTION(error_reporting)
                        zend_ini_entry *p = EG(error_reporting_ini_entry);
 
                        if (!p) {
-                               p = zend_hash_find_ptr(EG(ini_directives), CG(known_strings)[ZEND_STR_ERROR_REPORTING]);
+                               p = zend_hash_find_ptr(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING));
                                if (p) {
                                        EG(error_reporting_ini_entry) = p;
                                } else {
@@ -809,7 +809,7 @@ ZEND_FUNCTION(error_reporting)
                                        ALLOC_HASHTABLE(EG(modified_ini_directives));
                                        zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
                                }
-                               if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), CG(known_strings)[ZEND_STR_ERROR_REPORTING], p) != NULL)) {
+                               if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), p) != NULL)) {
                                        p->orig_value = p->value;
                                        p->orig_modifiable = p->modifiable;
                                        p->modified = 1;
@@ -2659,9 +2659,9 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                                lineno = skip->opline->lineno;
                        }
                        ZVAL_STR_COPY(&tmp, filename);
-                       zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_FILE], &tmp);
+                       zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
                        ZVAL_LONG(&tmp, lineno);
-                       zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_LINE], &tmp);
+                       zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
 
                        /* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
                         * and debug_baktrace() might have been called by the error_handler. in this case we don't
@@ -2679,9 +2679,9 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                                }
                                if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
                                        ZVAL_STR_COPY(&tmp, prev->func->op_array.filename);
-                                       zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_FILE], &tmp);
+                                       zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
                                        ZVAL_LONG(&tmp, prev->opline->lineno);
-                                       zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_LINE], &tmp);
+                                       zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
                                        break;
                                }
                                prev_call = prev;
@@ -2707,7 +2707,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
 
                if (function_name) {
                        ZVAL_STR_COPY(&tmp, function_name);
-                       zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_FUNCTION], &tmp);
+                       zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp);
 
                        if (object) {
                                if (func->common.scope) {
@@ -2717,27 +2717,27 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                                } else {
                                        ZVAL_STR(&tmp, object->handlers->get_class_name(object));
                                }
-                               zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_CLASS], &tmp);
+                               zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_CLASS), &tmp);
                                if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
                                        ZVAL_OBJ(&tmp, object);
-                                       zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_OBJECT], &tmp);
+                                       zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_OBJECT), &tmp);
                                        Z_ADDREF(tmp);
                                }
 
-                               ZVAL_INTERNED_STR(&tmp, CG(known_strings)[ZEND_STR_OBJECT_OPERATOR]);
-                               zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_TYPE], &tmp);
+                               ZVAL_INTERNED_STR(&tmp, ZSTR_KNOWN(ZEND_STR_OBJECT_OPERATOR));
+                               zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_TYPE), &tmp);
                        } else if (func->common.scope) {
                                ZVAL_STR_COPY(&tmp, func->common.scope->name);
-                               zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_CLASS], &tmp);
-                               ZVAL_INTERNED_STR(&tmp, CG(known_strings)[ZEND_STR_PAAMAYIM_NEKUDOTAYIM]);
-                               zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_TYPE], &tmp);
+                               zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_CLASS), &tmp);
+                               ZVAL_INTERNED_STR(&tmp, ZSTR_KNOWN(ZEND_STR_PAAMAYIM_NEKUDOTAYIM));
+                               zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_TYPE), &tmp);
                        }
 
                        if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
                                func->type != ZEND_EVAL_CODE) {
 
                                debug_backtrace_get_args(call, &tmp);
-                               zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_ARGS], &tmp);
+                               zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_ARGS), &tmp);
                        }
                } else {
                        /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
@@ -2746,30 +2746,30 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
 
                        if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
                                /* can happen when calling eval from a custom sapi */
-                               pseudo_function_name = CG(known_strings)[ZEND_STR_UNKNOWN];
+                               pseudo_function_name = ZSTR_KNOWN(ZEND_STR_UNKNOWN);
                                build_filename_arg = 0;
                        } else
                        switch (ptr->opline->extended_value) {
                                case ZEND_EVAL:
-                                       pseudo_function_name = CG(known_strings)[ZEND_STR_EVAL];
+                                       pseudo_function_name = ZSTR_KNOWN(ZEND_STR_EVAL);
                                        build_filename_arg = 0;
                                        break;
                                case ZEND_INCLUDE:
-                                       pseudo_function_name = CG(known_strings)[ZEND_STR_INCLUDE];
+                                       pseudo_function_name = ZSTR_KNOWN(ZEND_STR_INCLUDE);
                                        break;
                                case ZEND_REQUIRE:
-                                       pseudo_function_name = CG(known_strings)[ZEND_STR_REQUIRE];
+                                       pseudo_function_name = ZSTR_KNOWN(ZEND_STR_REQUIRE);
                                        break;
                                case ZEND_INCLUDE_ONCE:
-                                       pseudo_function_name = CG(known_strings)[ZEND_STR_INCLUDE_ONCE];
+                                       pseudo_function_name = ZSTR_KNOWN(ZEND_STR_INCLUDE_ONCE);
                                        break;
                                case ZEND_REQUIRE_ONCE:
-                                       pseudo_function_name = CG(known_strings)[ZEND_STR_REQUIRE_ONCE];
+                                       pseudo_function_name = ZSTR_KNOWN(ZEND_STR_REQUIRE_ONCE);
                                        break;
                                default:
                                        /* this can actually happen if you use debug_backtrace() in your error_handler and
                                         * you're in the top-scope */
-                                       pseudo_function_name = CG(known_strings)[ZEND_STR_UNKNOWN];
+                                       pseudo_function_name = ZSTR_KNOWN(ZEND_STR_UNKNOWN);
                                        build_filename_arg = 0;
                                        break;
                        }
@@ -2785,11 +2785,11 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
 
                                ZVAL_STR_COPY(&tmp, include_filename);
                                zend_hash_next_index_insert_new(Z_ARRVAL(arg_array), &tmp);
-                               zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_ARGS], &arg_array);
+                               zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_ARGS), &arg_array);
                        }
 
                        ZVAL_INTERNED_STR(&tmp, pseudo_function_name);
-                       zend_hash_add_new(Z_ARRVAL(stack_frame), CG(known_strings)[ZEND_STR_FUNCTION], &tmp);
+                       zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp);
                }
 
                zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &stack_frame);
index 8b37d10994a57e325afbae199b3dddc344679836..6e7b30361f830217e8b0146f3dd3a82ce34403c9 100644 (file)
@@ -369,7 +369,7 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object) /* {
        invoke->internal_function.handler = ZEND_MN(Closure___invoke);
        invoke->internal_function.module = 0;
        invoke->internal_function.scope = zend_ce_closure;
-       invoke->internal_function.function_name = CG(known_strings)[ZEND_STR_MAGIC_INVOKE];
+       invoke->internal_function.function_name = ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE);
        return invoke;
 }
 /* }}} */
@@ -509,12 +509,12 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp) /* {{{
        if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) {
                HashTable *static_variables = closure->func.op_array.static_variables;
                ZVAL_ARR(&val, zend_array_dup(static_variables));
-               zend_hash_update(debug_info, CG(known_strings)[ZEND_STR_STATIC], &val);
+               zend_hash_update(debug_info, ZSTR_KNOWN(ZEND_STR_STATIC), &val);
        }
 
        if (Z_TYPE(closure->this_ptr) != IS_UNDEF) {
                Z_ADDREF(closure->this_ptr);
-               zend_hash_update(debug_info, CG(known_strings)[ZEND_STR_THIS], &closure->this_ptr);
+               zend_hash_update(debug_info, ZSTR_KNOWN(ZEND_STR_THIS), &closure->this_ptr);
        }
 
        if (arg_info &&
index 2fc6fb08ecb3e7cc797968defad076bfe462d767..88d71925a83ebd4097951d7614562f48214ab5a5 100644 (file)
@@ -3467,13 +3467,7 @@ int zend_compile_func_chr(znode *result, zend_ast_list *args) /* {{{ */
                zend_long c = Z_LVAL_P(zend_ast_get_zval(args->child[0])) & 0xff;
 
                result->op_type = IS_CONST;
-               if (CG(one_char_string)[c]) {
-                       ZVAL_INTERNED_STR(&result->u.constant, CG(one_char_string)[c]);
-               } else {
-                       ZVAL_NEW_STR(&result->u.constant, zend_string_alloc(1, 0));
-                       Z_STRVAL_P(&result->u.constant)[0] = (char)c;
-                       Z_STRVAL_P(&result->u.constant)[1] = '\0';
-               }
+               ZVAL_INTERNED_STR(&result->u.constant, ZSTR_CHAR(c));
                return SUCCESS;
        } else {
                return FAILURE;
@@ -8216,11 +8210,7 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
                                        return;
                                }
                                c = (zend_uchar) Z_STRVAL_P(container)[offset];
-                               if (CG(one_char_string)[c]) {
-                                       ZVAL_INTERNED_STR(&result, CG(one_char_string)[c]);
-                               } else {
-                                       ZVAL_NEW_STR(&result, zend_string_init((char *) &c, 1, 0));
-                               }
+                               ZVAL_INTERNED_STR(&result, ZSTR_CHAR(c));
                        } else if (Z_TYPE_P(container) <= IS_FALSE) {
                                ZVAL_NULL(&result);
                        } else {
index 17f80aa19a0e77e2fed1e3c834d467b5156f5660..14dd08dad0271185caaa579310e0115581a4f0e9 100644 (file)
@@ -489,6 +489,10 @@ ZEND_API int zend_register_constant(zend_constant *c)
        printf("Registering constant for module %d\n", c->module_number);
 #endif
 
+    if (c->module_number != PHP_USER_CONSTANT) {
+               c->name = zend_new_interned_string(c->name);
+       }
+
        if (!(c->flags & CONST_CS)) {
                lowercase_name = zend_string_alloc(ZSTR_LEN(c->name), c->flags & CONST_PERSISTENT);
                zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ZSTR_VAL(c->name), ZSTR_LEN(c->name));
index d9db617855ca9e45a1fe5fc0889d726bea53f514..9895b09556ca902e1ad40b9f3156a1837f64984f 100644 (file)
@@ -88,18 +88,18 @@ void zend_exception_set_previous(zend_object *exception, zend_object *add_previo
        ZVAL_OBJ(&zv, exception);
        ex = &zv;
        do {
-               ancestor = zend_read_property_ex(i_get_exception_base(&pv), &pv, CG(known_strings)[ZEND_STR_PREVIOUS], 1, &rv);
+               ancestor = zend_read_property_ex(i_get_exception_base(&pv), &pv, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv);
                while (Z_TYPE_P(ancestor) == IS_OBJECT) {
                        if (Z_OBJ_P(ancestor) == Z_OBJ_P(ex)) {
                                OBJ_RELEASE(add_previous);
                                return;
                        }
-                       ancestor = zend_read_property_ex(i_get_exception_base(ancestor), ancestor, CG(known_strings)[ZEND_STR_PREVIOUS], 1, &rv);
+                       ancestor = zend_read_property_ex(i_get_exception_base(ancestor), ancestor, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv);
                }
                base_ce = i_get_exception_base(ex);
-               previous = zend_read_property_ex(base_ce, ex, CG(known_strings)[ZEND_STR_PREVIOUS], 1, &rv);
+               previous = zend_read_property_ex(base_ce, ex, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv);
                if (Z_TYPE_P(previous) == IS_NULL) {
-                       zend_update_property_ex(base_ce, ex, CG(known_strings)[ZEND_STR_PREVIOUS], &pv);
+                       zend_update_property_ex(base_ce, ex, ZSTR_KNOWN(ZEND_STR_PREVIOUS), &pv);
                        GC_REFCOUNT(add_previous)--;
                        return;
                }
@@ -223,17 +223,17 @@ static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type,
 
        if (EXPECTED(class_type != zend_ce_parse_error || !(filename = zend_get_compiled_filename()))) {
                ZVAL_STRING(&tmp, zend_get_executed_filename());
-               zend_update_property_ex(base_ce, &obj, CG(known_strings)[ZEND_STR_FILE], &tmp);
+               zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
                zval_ptr_dtor(&tmp);
                ZVAL_LONG(&tmp, zend_get_executed_lineno());
-               zend_update_property_ex(base_ce, &obj, CG(known_strings)[ZEND_STR_LINE], &tmp);
+               zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
        } else {
                ZVAL_STR(&tmp, filename);
-               zend_update_property_ex(base_ce, &obj, CG(known_strings)[ZEND_STR_FILE], &tmp);
+               zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
                ZVAL_LONG(&tmp, zend_get_compiled_lineno());
-               zend_update_property_ex(base_ce, &obj, CG(known_strings)[ZEND_STR_LINE], &tmp);
+               zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
        }
-       zend_update_property_ex(base_ce, &obj, CG(known_strings)[ZEND_STR_TRACE], &trace);
+       zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_TRACE), &trace);
 
        return object;
 }
@@ -289,16 +289,16 @@ ZEND_METHOD(exception, __construct)
 
        if (message) {
                ZVAL_STR(&tmp, message);
-               zend_update_property_ex(base_ce, object, CG(known_strings)[ZEND_STR_MESSAGE], &tmp);
+               zend_update_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp);
        }
 
        if (code) {
                ZVAL_LONG(&tmp, code);
-               zend_update_property_ex(base_ce, object, CG(known_strings)[ZEND_STR_CODE], &tmp);
+               zend_update_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_CODE), &tmp);
        }
 
        if (previous) {
-               zend_update_property_ex(base_ce, object, CG(known_strings)[ZEND_STR_PREVIOUS], previous);
+               zend_update_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_PREVIOUS), previous);
        }
 }
 /* }}} */
@@ -306,9 +306,9 @@ ZEND_METHOD(exception, __construct)
 /* {{{ proto Exception::__wakeup()
    Exception unserialize checks */
 #define CHECK_EXC_TYPE(id, type) \
-       pvalue = zend_read_property_ex(i_get_exception_base(object), (object), CG(known_strings)[id], 1, &value); \
+       pvalue = zend_read_property_ex(i_get_exception_base(object), (object), ZSTR_KNOWN(id), 1, &value); \
        if (Z_TYPE_P(pvalue) != IS_NULL && Z_TYPE_P(pvalue) != type) { \
-               zend_unset_property(i_get_exception_base(object), object, ZSTR_VAL(CG(known_strings)[id]), ZSTR_LEN(CG(known_strings)[id])); \
+               zend_unset_property(i_get_exception_base(object), object, ZSTR_VAL(ZSTR_KNOWN(id)), ZSTR_LEN(ZSTR_KNOWN(id))); \
        }
 
 ZEND_METHOD(exception, __wakeup)
@@ -358,31 +358,31 @@ ZEND_METHOD(error_exception, __construct)
 
        if (message) {
                ZVAL_STRING(&tmp, message);
-               zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_MESSAGE], &tmp);
+               zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp);
                zval_ptr_dtor(&tmp);
        }
 
        if (code) {
                ZVAL_LONG(&tmp, code);
-               zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_CODE], &tmp);
+               zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_CODE), &tmp);
        }
 
        if (previous) {
-               zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_PREVIOUS], previous);
+               zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_PREVIOUS), previous);
        }
 
        ZVAL_LONG(&tmp, severity);
-       zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_SEVERITY], &tmp);
+       zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_SEVERITY), &tmp);
 
        if (argc >= 4) {
                ZVAL_STRING(&tmp, filename);
-               zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_FILE], &tmp);
+               zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
                zval_ptr_dtor(&tmp);
        if (argc < 5) {
            lineno = 0; /* invalidate lineno */
        }
                ZVAL_LONG(&tmp, lineno);
-               zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_LINE], &tmp);
+               zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
        }
 }
 /* }}} */
@@ -393,9 +393,9 @@ ZEND_METHOD(error_exception, __construct)
        }
 
 #define GET_PROPERTY(object, id) \
-       zend_read_property_ex(i_get_exception_base(object), (object), CG(known_strings)[id], 0, &rv)
+       zend_read_property_ex(i_get_exception_base(object), (object), ZSTR_KNOWN(id), 0, &rv)
 #define GET_PROPERTY_SILENT(object, id) \
-       zend_read_property_ex(i_get_exception_base(object), (object), CG(known_strings)[id], 1, &rv)
+       zend_read_property_ex(i_get_exception_base(object), (object), ZSTR_KNOWN(id), 1, &rv)
 
 /* {{{ proto string Exception|Error::getFile()
    Get the file in which the exception occurred */
@@ -547,14 +547,14 @@ static void _build_trace_string(smart_str *str, HashTable *ht, uint32_t num) /*
        smart_str_append_long(str, num);
        smart_str_appendc(str, ' ');
 
-       file = zend_hash_find(ht, CG(known_strings)[ZEND_STR_FILE]);
+       file = zend_hash_find(ht, ZSTR_KNOWN(ZEND_STR_FILE));
        if (file) {
                if (Z_TYPE_P(file) != IS_STRING) {
                        zend_error(E_WARNING, "Function name is no string");
                        smart_str_appends(str, "[unknown function]");
                } else{
                        zend_long line;
-                       tmp = zend_hash_find(ht, CG(known_strings)[ZEND_STR_LINE]);
+                       tmp = zend_hash_find(ht, ZSTR_KNOWN(ZEND_STR_LINE));
                        if (tmp) {
                                if (Z_TYPE_P(tmp) == IS_LONG) {
                                        line = Z_LVAL_P(tmp);
@@ -573,11 +573,11 @@ static void _build_trace_string(smart_str *str, HashTable *ht, uint32_t num) /*
        } else {
                smart_str_appends(str, "[internal function]: ");
        }
-       TRACE_APPEND_KEY(CG(known_strings)[ZEND_STR_CLASS]);
-       TRACE_APPEND_KEY(CG(known_strings)[ZEND_STR_TYPE]);
-       TRACE_APPEND_KEY(CG(known_strings)[ZEND_STR_FUNCTION]);
+       TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_CLASS));
+       TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_TYPE));
+       TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_FUNCTION));
        smart_str_appendc(str, '(');
-       tmp = zend_hash_find(ht, CG(known_strings)[ZEND_STR_ARGS]);
+       tmp = zend_hash_find(ht, ZSTR_KNOWN(ZEND_STR_ARGS));
        if (tmp) {
                if (Z_TYPE_P(tmp) == IS_ARRAY) {
                        size_t last_len = ZSTR_LEN(str->s);
@@ -614,7 +614,7 @@ ZEND_METHOD(exception, getTraceAsString)
        object = getThis();
        base_ce = i_get_exception_base(object);
 
-       trace = zend_read_property_ex(base_ce, object, CG(known_strings)[ZEND_STR_TRACE], 1, &rv);
+       trace = zend_read_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_TRACE), 1, &rv);
        if (Z_TYPE_P(trace) != IS_ARRAY) {
                RETURN_FALSE;
        }
@@ -736,7 +736,7 @@ ZEND_METHOD(exception, __toString)
        /* We store the result in the private property string so we can access
         * the result in uncaught exception handlers without memleaks. */
        ZVAL_STR(&tmp, str);
-       zend_update_property_ex(base_ce, exception, CG(known_strings)[ZEND_STR_STRING], &tmp);
+       zend_update_property_ex(base_ce, exception, ZSTR_KNOWN(ZEND_STR_STRING), &tmp);
 
        RETURN_STR(str);
 }
@@ -896,12 +896,12 @@ ZEND_API ZEND_COLD zend_object *zend_throw_exception(zend_class_entry *exception
 
        if (message) {
                ZVAL_STRING(&tmp, message);
-               zend_update_property_ex(exception_ce, &ex, CG(known_strings)[ZEND_STR_MESSAGE], &tmp);
+               zend_update_property_ex(exception_ce, &ex, ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp);
                zval_ptr_dtor(&tmp);
        }
        if (code) {
                ZVAL_LONG(&tmp, code);
-               zend_update_property_ex(exception_ce, &ex, CG(known_strings)[ZEND_STR_CODE], &tmp);
+               zend_update_property_ex(exception_ce, &ex, ZSTR_KNOWN(ZEND_STR_CODE), &tmp);
        }
 
        zend_throw_exception_internal(&ex);
@@ -930,7 +930,7 @@ ZEND_API ZEND_COLD zend_object *zend_throw_error_exception(zend_class_entry *exc
        zend_object *obj = zend_throw_exception(exception_ce, message, code);
        ZVAL_OBJ(&ex, obj);
        ZVAL_LONG(&tmp, severity);
-       zend_update_property_ex(zend_ce_error_exception, &ex, CG(known_strings)[ZEND_STR_SEVERITY], &tmp);
+       zend_update_property_ex(zend_ce_error_exception, &ex, ZSTR_KNOWN(ZEND_STR_SEVERITY), &tmp);
        return obj;
 }
 /* }}} */
@@ -983,7 +983,7 @@ ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* {
                        if (Z_TYPE(tmp) != IS_STRING) {
                                zend_error(E_WARNING, "%s::__toString() must return a string", ZSTR_VAL(ce_exception->name));
                        } else {
-                               zend_update_property_ex(i_get_exception_base(&exception), &exception, CG(known_strings)[ZEND_STR_STRING], &tmp);
+                               zend_update_property_ex(i_get_exception_base(&exception), &exception, ZSTR_KNOWN(ZEND_STR_STRING), &tmp);
                        }
                }
                zval_ptr_dtor(&tmp);
index 68f5b3ce6cab6447371427b7643b869d5913b0b7..451185969c91cc239221f5daf78e19196207efd1 100644 (file)
@@ -1264,11 +1264,7 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
 
        if (result) {
                /* Return the new character */
-               if (CG(one_char_string)[c]) {
-                       ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
-               } else {
-                       ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(str) + offset, 1, 0));
-               }
+               ZVAL_INTERNED_STR(result, ZSTR_CHAR(c));
        }
 }
 
@@ -1781,11 +1777,7 @@ try_string_offset:
                                ? (zend_long)Z_STRLEN_P(container) + offset : offset;
                        c = (zend_uchar)Z_STRVAL_P(container)[real_offset];
 
-                       if (CG(one_char_string)[c]) {
-                               ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
-                       } else {
-                               ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(container) + real_offset, 1, 0));
-                       }
+                       ZVAL_INTERNED_STR(result, ZSTR_CHAR(c));
                }
        } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (/*dim_type == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
index 7747fa4e585555b4df8614f245c720d297cebc47..07eb7a8ef34d3f02966ba74f3270562e036127bf 100644 (file)
@@ -975,7 +975,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
        }
 
        if (!EG(autoload_func)) {
-               zend_function *func = zend_hash_find_ptr(EG(function_table), CG(known_strings)[ZEND_STR_MAGIC_AUTOLOAD]);
+               zend_function *func = zend_hash_find_ptr(EG(function_table), ZSTR_KNOWN(ZEND_STR_MAGIC_AUTOLOAD));
                if (func) {
                        EG(autoload_func) = func;
                } else {
index 3440edfc69bbce1a92aba91a9f8026f63fac5f81..151f47c71fa8a1a9080759debf2aac9241727b14 100644 (file)
@@ -110,11 +110,6 @@ struct _zend_compiler_globals {
 
        zend_arena *arena;
 
-       zend_string *empty_string;
-       zend_string *one_char_string[256];
-       zend_string **known_strings;
-       uint32_t    known_strings_count;
-
        HashTable interned_strings;
 
        const zend_encoding **script_encoding_list;
index 4dd1bbe7c9246c69c93f9b113395ada63fe6330e..e6070dfb9128a2b2dcc11d475f9fe6b4f5e304c8 100644 (file)
@@ -359,7 +359,7 @@ ZEND_API int zend_alter_ini_entry_ex(zend_string *name, zend_string *new_value,
                ini_entry->orig_value = ini_entry->value;
                ini_entry->orig_modifiable = modifiable;
                ini_entry->modified = 1;
-               zend_hash_add_ptr(EG(modified_ini_directives), name, ini_entry);
+               zend_hash_add_ptr(EG(modified_ini_directives), ini_entry->name, ini_entry);
        }
 
        duplicate = zend_string_copy(new_value);
index 92524c69e0386887961b8f239f710c78dd2b53d1..9970ce3a0724f9e938ec903150aca429efac747b 100644 (file)
@@ -1030,7 +1030,7 @@ function_call:
 
 class_name:
                T_STATIC
-                       { zval zv; ZVAL_INTERNED_STR(&zv, CG(known_strings)[ZEND_STR_STATIC]);
+                       { zval zv; ZVAL_INTERNED_STR(&zv, ZSTR_KNOWN(ZEND_STR_STATIC));
                          $$ = zend_ast_create_zval_ex(&zv, ZEND_NAME_NOT_FQ); }
        |       name { $$ = $1; }
 ;
index 4ec90ba0969cf8ee22f1bab8b8ef633f40fd2ea6..66de460a309e6952aa1e22a011640c72453afbaa 100644 (file)
@@ -1682,7 +1682,7 @@ int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **f
 
        ce = Z_OBJCE_P(obj);
 
-       if ((func = zend_hash_find(&ce->function_table, CG(known_strings)[ZEND_STR_MAGIC_INVOKE])) == NULL) {
+       if ((func = zend_hash_find(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE))) == NULL) {
                return FAILURE;
        }
        *fptr_ptr = Z_FUNC_P(func);
index 37fa5e98259da4b8f9f9ce8c8932abdcf9a158a0..41d1ca62e1eaf215914e8c8bac67e287b4aca31e 100644 (file)
@@ -525,11 +525,7 @@ try_again:
                        break;
                }
                case IS_TRUE:
-                       if (CG(one_char_string)['1']) {
-                               ZVAL_INTERNED_STR(op, CG(one_char_string)['1']);
-                       } else {
-                               ZVAL_NEW_STR(op, zend_string_init("1", 1, 0));
-                       }
+                       ZVAL_INTERNED_STR(op, ZSTR_CHAR('1'));
                        break;
                case IS_STRING:
                        break;
@@ -677,7 +673,7 @@ try_again:
                        zval tmp;
                        ZVAL_COPY_VALUE(&tmp, op);
                        object_init(op);
-                       zend_hash_add_new(Z_OBJPROP_P(op), CG(known_strings)[ZEND_STR_SCALAR], &tmp);
+                       zend_hash_add_new(Z_OBJPROP_P(op), ZSTR_KNOWN(ZEND_STR_SCALAR), &tmp);
                        break;
                }
        }
@@ -850,11 +846,7 @@ try_again:
                case IS_FALSE:
                        return ZSTR_EMPTY_ALLOC();
                case IS_TRUE:
-                       if (CG(one_char_string)['1']) {
-                               return CG(one_char_string)['1'];
-                       } else {
-                               return zend_string_init("1", 1, 0);
-                       }
+                       return ZSTR_CHAR('1');
                case IS_RESOURCE: {
                        char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
                        int len;
@@ -1364,11 +1356,7 @@ try_again:
 
                        if (Z_STRLEN_P(op1) == 1) {
                                zend_uchar not = (zend_uchar) ~*Z_STRVAL_P(op1);
-                               if (CG(one_char_string)[not]) {
-                                       ZVAL_INTERNED_STR(result, CG(one_char_string)[not]);
-                               } else {
-                                       ZVAL_NEW_STR(result, zend_string_init((char *) &not, 1, 0));
-                               }
+                               ZVAL_INTERNED_STR(result, ZSTR_CHAR(not));
                        } else {
                                ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(op1), 0));
                                for (i = 0; i < Z_STRLEN_P(op1); i++) {
@@ -1416,11 +1404,7 @@ ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op
                                if (result==op1) {
                                        zend_string_release(Z_STR_P(result));
                                }
-                               if (CG(one_char_string)[or]) {
-                                       ZVAL_INTERNED_STR(result, CG(one_char_string)[or]);
-                               } else {
-                                       ZVAL_NEW_STR(result, zend_string_init((char *) &or, 1, 0));
-                               }
+                               ZVAL_INTERNED_STR(result, ZSTR_CHAR(or));
                                return SUCCESS;
                        }
                        longer = op1;
@@ -1498,11 +1482,7 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o
                                if (result==op1) {
                                        zend_string_release(Z_STR_P(result));
                                }
-                               if (CG(one_char_string)[and]) {
-                                       ZVAL_INTERNED_STR(result, CG(one_char_string)[and]);
-                               } else {
-                                       ZVAL_NEW_STR(result, zend_string_init((char *) &and, 1, 0));
-                               }
+                               ZVAL_INTERNED_STR(result, ZSTR_CHAR(and));
                                return SUCCESS;
                        }
                        longer = op1;
@@ -1580,11 +1560,7 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o
                                if (result==op1) {
                                        zend_string_release(Z_STR_P(result));
                                }
-                               if (CG(one_char_string)[xor]) {
-                                       ZVAL_INTERNED_STR(result, CG(one_char_string)[xor]);
-                               } else {
-                                       ZVAL_NEW_STR(result, zend_string_init((char *) &xor, 1, 0));
-                               }
+                               ZVAL_INTERNED_STR(result, ZSTR_CHAR(xor));
                                return SUCCESS;
                        }
                        longer = op1;
@@ -2297,12 +2273,7 @@ static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */
 
        if (Z_STRLEN_P(str) == 0) {
                zend_string_release(Z_STR_P(str));
-               if (CG(one_char_string)['1']) {
-                       ZVAL_INTERNED_STR(str, CG(one_char_string)['1']);
-               } else {
-                       Z_STR_P(str) = zend_string_init("1", sizeof("1")-1, 0);
-                       Z_TYPE_INFO_P(str) = IS_STRING_EX;
-               }
+               ZVAL_INTERNED_STR(str, ZSTR_CHAR('1'));
                return;
        }
 
index dbc44870c21a55dfd9ec854e9437be0c0c5e9125..d3fbdf2f19e5bbc618e979ee1233c2845111cad4 100644 (file)
 #include "zend_globals.h"
 
 ZEND_API zend_string *(*zend_new_interned_string)(zend_string *str);
-ZEND_API void (*zend_interned_strings_snapshot)(void);
-ZEND_API void (*zend_interned_strings_restore)(void);
 
-static zend_string *zend_new_interned_string_int(zend_string *str);
-static void zend_interned_strings_snapshot_int(void);
-static void zend_interned_strings_restore_int(void);
+static zend_string *zend_new_interned_string_permanent(zend_string *str);
+static zend_string *zend_new_interned_string_request(zend_string *str);
+
+/* Any strings interned in the startup phase. Common to all the threads,
+   won't be free'd until process exit. If we want an ability to 
+   add permanent strings even after startup, it would be still
+   possible on costs of locking in the thread safe builds. */
+static HashTable interned_strings_permanent;
+
+static zend_new_interned_string_func_t interned_string_request_handler = zend_new_interned_string_request;
+static zend_string_copy_storage_func_t interned_string_copy_storage = NULL;
+
+ZEND_API zend_string  *zend_empty_string = NULL;
+ZEND_API zend_string  *zend_one_char_string[256];
+ZEND_API zend_string **zend_known_strings = NULL;
 
 ZEND_API zend_ulong zend_hash_func(const char *str, size_t len)
 {
        return zend_inline_hash_func(str, len);
 }
 
-#ifndef ZTS
 static void _str_dtor(zval *zv)
 {
        zend_string *str = Z_STR_P(zv);
        pefree(str, GC_FLAGS(str) & IS_STR_PERSISTENT);
 }
-#endif
-
-/* Readonly, so assigned also per thread. */
-static const zend_string **known_interned_strings = NULL;
-static uint32_t known_interned_strings_count = 0;
-
-ZEND_API uint32_t zend_intern_known_strings(const char **strings, uint32_t count)
-{
-       uint32_t i, old_count = known_interned_strings_count;
-
-       known_interned_strings = perealloc(known_interned_strings, sizeof(char*) * (old_count + count), 1);
-       for (i = 0; i < count; i++) {
-#ifndef ZTS
-               zend_string *str = zend_string_init(strings[i], strlen(strings[i]), 1);
-               known_interned_strings[known_interned_strings_count + i] =
-                       zend_new_interned_string_int(str);
-#else
-               known_interned_strings[known_interned_strings_count + i] =
-                       zend_zts_interned_string_init(strings[i], strlen(strings[i]));
-#endif
-       }
-       known_interned_strings_count = old_count + count;
-       return old_count;
-}
 
 static const char *known_strings[] = {
 #define _ZEND_STR_DSC(id, str) str,
@@ -72,175 +57,202 @@ ZEND_KNOWN_STRINGS(_ZEND_STR_DSC)
        NULL
 };
 
-void zend_known_interned_strings_init(zend_string ***strings, uint32_t *count)
+static void zend_init_interned_strings_ht(HashTable *interned_strings, int permanent)
 {
-       *strings = (zend_string **)known_interned_strings;
-       *count   = known_interned_strings_count;
+       zend_hash_init(interned_strings, 1024, NULL, _str_dtor, permanent);
+
+       interned_strings->nTableMask = -interned_strings->nTableSize;
+       HT_SET_DATA_ADDR(interned_strings, pemalloc(HT_SIZE(interned_strings), permanent));
+       HT_HASH_RESET(interned_strings);
+       interned_strings->u.flags |= HASH_FLAG_INITIALIZED;
 }
 
-void zend_interned_strings_init(void)
+ZEND_API void zend_interned_strings_init(void)
 {
-#ifndef ZTS
+       char s[2];
+       int i;
        zend_string *str;
 
-       zend_hash_init(&CG(interned_strings), 1024, NULL, _str_dtor, 1);
+       zend_init_interned_strings_ht(&interned_strings_permanent, 1);
 
-       CG(interned_strings).nTableMask = -CG(interned_strings).nTableSize;
-       HT_SET_DATA_ADDR(&CG(interned_strings), pemalloc(HT_SIZE(&CG(interned_strings)), 1));
-       HT_HASH_RESET(&CG(interned_strings));
-       CG(interned_strings).u.flags |= HASH_FLAG_INITIALIZED;
+       zend_new_interned_string = zend_new_interned_string_permanent;
 
        /* interned empty string */
        str = zend_string_alloc(sizeof("")-1, 1);
        ZSTR_VAL(str)[0] = '\000';
-       CG(empty_string) = zend_new_interned_string_int(str);
-#endif
+       zend_empty_string = zend_new_interned_string_permanent(str);
 
-       /* one char strings (the actual interned strings are going to be created by ext/opcache) */
-       memset(CG(one_char_string), 0, sizeof(CG(one_char_string)));
+       s[1] = 0;
+       for (i = 0; i < 256; i++) {
+               s[0] = i;
+               zend_one_char_string[i] = zend_new_interned_string_permanent(zend_string_init(s, 1, 1));
+       }
 
        /* known strings */
-       zend_intern_known_strings(known_strings, (sizeof(known_strings) / sizeof(known_strings[0])) - 1);
-       zend_known_interned_strings_init(&CG(known_strings), &CG(known_strings_count));
-
-       zend_new_interned_string = zend_new_interned_string_int;
-       zend_interned_strings_snapshot = zend_interned_strings_snapshot_int;
-       zend_interned_strings_restore = zend_interned_strings_restore_int;
+       zend_known_strings = pemalloc(sizeof(zend_string*) * ((sizeof(known_strings) / sizeof(known_strings[0]) - 1)), 1);
+       for (i = 0; i < (sizeof(known_strings) / sizeof(known_strings[0])) - 1; i++) {
+               str = zend_string_init(known_strings[i], strlen(known_strings[i]), 1);
+               zend_known_strings[i] = zend_new_interned_string_permanent(str);
+       }
 }
 
-void zend_interned_strings_dtor(void)
+ZEND_API void zend_interned_strings_dtor(void)
 {
-#ifndef ZTS
-       zend_hash_destroy(&CG(interned_strings));
-#else
-       uint32_t i;
+       zend_hash_destroy(&interned_strings_permanent);
 
-       for (i = 0; i < CG(known_strings_count); i++) {
-               zend_zts_interned_string_free(&CG(known_strings)[i]);
-       }
-#endif
-       free(CG(known_strings));
-       CG(known_strings) = NULL;
-       CG(known_strings_count) = 0;
-       known_interned_strings = NULL;
-       known_interned_strings_count = 0;
+       free(zend_known_strings);
+       zend_known_strings = NULL;
 }
 
-static zend_string *zend_new_interned_string_int(zend_string *str)
+static zend_always_inline zend_string *zend_interned_string_ht_lookup(zend_string *str, HashTable *interned_strings)
 {
-#ifndef ZTS
        zend_ulong h;
        uint32_t nIndex;
        uint32_t idx;
        Bucket *p;
 
-       if (ZSTR_IS_INTERNED(str)) {
-               return str;
-       }
-
        h = zend_string_hash_val(str);
-       nIndex = h | CG(interned_strings).nTableMask;
-       idx = HT_HASH(&CG(interned_strings), nIndex);
+       nIndex = h | interned_strings->nTableMask;
+       idx = HT_HASH(interned_strings, nIndex);
        while (idx != HT_INVALID_IDX) {
-               p = HT_HASH_TO_BUCKET(&CG(interned_strings), idx);
+               p = HT_HASH_TO_BUCKET(interned_strings, idx);
                if ((p->h == h) && (ZSTR_LEN(p->key) == ZSTR_LEN(str))) {
                        if (!memcmp(ZSTR_VAL(p->key), ZSTR_VAL(str), ZSTR_LEN(str))) {
-                               zend_string_release(str);
                                return p->key;
                        }
                }
                idx = Z_NEXT(p->val);
        }
 
+       return NULL;
+}
+
+static zend_never_inline void zend_string_table_grow(HashTable *interned_strings)
+{
+       if (EXPECTED(interned_strings->nTableSize < HT_MAX_SIZE)) {     /* Let's double the table size */
+               void *new_data;
+               void *old_data = HT_GET_DATA_ADDR(interned_strings);
+               Bucket *old_buckets = interned_strings->arData;
+
+               interned_strings->nTableSize += interned_strings->nTableSize;
+               interned_strings->nTableMask = -interned_strings->nTableSize;
+               new_data = pemalloc(HT_SIZE(interned_strings), interned_strings->u.flags & HASH_FLAG_PERSISTENT);
+
+               HT_SET_DATA_ADDR(interned_strings, new_data);
+               memcpy(interned_strings->arData, old_buckets, sizeof(Bucket) * interned_strings->nNumUsed);
+               pefree(old_data, interned_strings->u.flags & HASH_FLAG_PERSISTENT);
+               zend_hash_rehash(interned_strings);
+       }
+}
+
+/* This function might be not thread safe at least because it would update the
+   hash val in the passed string. Be sure it is called in the appropriate context. */
+static zend_always_inline zend_string *zend_add_interned_string(zend_string *str, HashTable *interned_strings, uint32_t flags)
+{
+       zend_ulong h;
+       uint32_t nIndex;
+       uint32_t idx;
+       Bucket *p;
+
+       h = zend_string_hash_val(str);
+
        GC_REFCOUNT(str) = 1;
-       GC_FLAGS(str) |= IS_STR_INTERNED;
-
-       if (CG(interned_strings).nNumUsed >= CG(interned_strings).nTableSize) {
-               if (CG(interned_strings).nTableSize < HT_MAX_SIZE) {    /* Let's double the table size */
-                       void *new_data;
-                       void *old_data = HT_GET_DATA_ADDR(&CG(interned_strings));
-                       Bucket *old_buckets = CG(interned_strings).arData;
-
-                       CG(interned_strings).nTableSize += CG(interned_strings).nTableSize;
-                       CG(interned_strings).nTableMask = -CG(interned_strings).nTableSize;
-                       new_data = malloc(HT_SIZE(&CG(interned_strings)));
-
-                       if (new_data) {
-                               HT_SET_DATA_ADDR(&CG(interned_strings), new_data);
-                               memcpy(CG(interned_strings).arData, old_buckets, sizeof(Bucket) * CG(interned_strings).nNumUsed);
-                               free(old_data);
-                               zend_hash_rehash(&CG(interned_strings));
-                       } else {
-                               CG(interned_strings).nTableSize = CG(interned_strings).nTableSize >> 1;
-                               CG(interned_strings).nTableMask = -CG(interned_strings).nTableSize;
-                       }
-               }
+       GC_FLAGS(str) |= IS_STR_INTERNED | flags;
+
+       if (UNEXPECTED(interned_strings->nNumUsed >= interned_strings->nTableSize)) {
+               zend_string_table_grow(interned_strings);
        }
 
-       idx = CG(interned_strings).nNumUsed++;
-       CG(interned_strings).nNumOfElements++;
-       p = CG(interned_strings).arData + idx;
+       idx = interned_strings->nNumUsed++;
+       interned_strings->nNumOfElements++;
+       p = interned_strings->arData + idx;
        p->h = h;
        p->key = str;
        Z_STR(p->val) = str;
        Z_TYPE_INFO(p->val) = IS_INTERNED_STRING_EX;
-       nIndex = h | CG(interned_strings).nTableMask;
-       Z_NEXT(p->val) = HT_HASH(&CG(interned_strings), nIndex);
-       HT_HASH(&CG(interned_strings), nIndex) = HT_IDX_TO_HASH(idx);
+       nIndex = h | interned_strings->nTableMask;
+       Z_NEXT(p->val) = HT_HASH(interned_strings, nIndex);
+       HT_HASH(interned_strings, nIndex) = HT_IDX_TO_HASH(idx);
 
        return str;
-#else
-       return str;
-#endif
 }
 
-static void zend_interned_strings_snapshot_int(void)
+ZEND_API zend_string *zend_interned_string_find_permanent(zend_string *str)
 {
-#ifndef ZTS
-       uint32_t idx;
-       Bucket *p;
+       return zend_interned_string_ht_lookup(str, &interned_strings_permanent);
+}
+
+
+static zend_string *zend_new_interned_string_permanent(zend_string *str)
+{
+       zend_string *ret;
+
+       if (ZSTR_IS_INTERNED(str)) {
+               return str;
+       }
 
-       idx = CG(interned_strings).nNumUsed;
-       while (idx > 0) {
-               idx--;
-               p = CG(interned_strings).arData + idx;
-               ZEND_ASSERT(GC_FLAGS(p->key) & IS_STR_PERSISTENT);
-               GC_FLAGS(p->key) |= IS_STR_PERMANENT;
+       ret = zend_interned_string_ht_lookup(str, &interned_strings_permanent);
+       if (ret) {
+               zend_string_release(str);
+               return ret;
        }
-#endif
+
+       return zend_add_interned_string(str, &interned_strings_permanent, IS_STR_PERMANENT);
 }
 
-static void zend_interned_strings_restore_int(void)
+static zend_string *zend_new_interned_string_request(zend_string *str)
 {
-#ifndef ZTS
-       uint32_t nIndex;
-       uint32_t idx;
-       Bucket *p;
+       zend_string *ret;
+
+       if (ZSTR_IS_INTERNED(str)) {
+               return str;
+       }
+
+       /* Check for permanent strings, the table is readonly at this point. */
+       ret = zend_interned_string_ht_lookup(str, &interned_strings_permanent);
+       if (ret) {
+               zend_string_release(str);
+               return ret;
+       }
+
+       ret = zend_interned_string_ht_lookup(str, &CG(interned_strings));
+       if (ret) {
+               zend_string_release(str);
+               return ret;
+       }
+
+       /* Create a short living interned, freed after the request. */
+       ret = zend_add_interned_string(str, &CG(interned_strings), 0);
+
+       return ret;
+}
+
+ZEND_API void zend_interned_strings_activate(void)
+{
+       zend_init_interned_strings_ht(&CG(interned_strings), 0);
+}
 
-       idx = CG(interned_strings).nNumUsed;
-       while (idx > 0) {
-               idx--;
-               p = CG(interned_strings).arData + idx;
-               if (GC_FLAGS(p->key) & IS_STR_PERMANENT) break;
-               CG(interned_strings).nNumUsed--;
-               CG(interned_strings).nNumOfElements--;
-
-               GC_FLAGS(p->key) &= ~IS_STR_INTERNED;
-               GC_REFCOUNT(p->key) = 1;
-               zend_string_free(p->key);
-
-               nIndex = p->h | CG(interned_strings).nTableMask;
-               if (HT_HASH(&CG(interned_strings), nIndex) == HT_IDX_TO_HASH(idx)) {
-                       HT_HASH(&CG(interned_strings), nIndex) = Z_NEXT(p->val);
-               } else {
-                       uint32_t prev = HT_HASH(&CG(interned_strings), nIndex);
-                       while (Z_NEXT(HT_HASH_TO_BUCKET(&CG(interned_strings), prev)->val) != idx) {
-                               prev = Z_NEXT(HT_HASH_TO_BUCKET(&CG(interned_strings), prev)->val);
-                       }
-                       Z_NEXT(HT_HASH_TO_BUCKET(&CG(interned_strings), prev)->val) = Z_NEXT(p->val);
-               }
-       }
-#endif
+ZEND_API void zend_interned_strings_deactivate(void)
+{
+       zend_hash_destroy(&CG(interned_strings));
+}
+
+ZEND_API void zend_interned_strings_set_request_storage_handler(zend_new_interned_string_func_t handler)
+{
+       interned_string_request_handler = handler;
+}
+
+ZEND_API void zend_interned_strings_set_permanent_storage_copy_handler(zend_string_copy_storage_func_t handler)
+{
+       interned_string_copy_storage = handler;
+}
+
+ZEND_API void zend_interned_strings_switch_storage(void)
+{
+       if (interned_string_copy_storage) {
+               interned_string_copy_storage();
+       }
+       zend_new_interned_string = interned_string_request_handler;
 }
 
 /*
index 025082e9c9f5dde80f11b7030a24e5a99bf0f9eb..77dd0839978d6e3aa29fb47a5f8ef17d8081647a 100644 (file)
 
 BEGIN_EXTERN_C()
 
-ZEND_API extern zend_string *(*zend_new_interned_string)(zend_string *str);
-ZEND_API extern void (*zend_interned_strings_snapshot)(void);
-ZEND_API extern void (*zend_interned_strings_restore)(void);
+typedef void (*zend_string_copy_storage_func_t)(void);
+typedef zend_string *(*zend_new_interned_string_func_t)(zend_string *str);
+
+ZEND_API extern zend_new_interned_string_func_t zend_new_interned_string;
 
 ZEND_API zend_ulong zend_hash_func(const char *str, size_t len);
-void zend_interned_strings_init(void);
-void zend_interned_strings_dtor(void);
-void zend_known_interned_strings_init(zend_string ***, uint32_t *);
+ZEND_API void zend_interned_strings_init(void);
+ZEND_API void zend_interned_strings_dtor(void);
+ZEND_API void zend_interned_strings_activate(void);
+ZEND_API void zend_interned_strings_deactivate(void);
+ZEND_API zend_string *zend_interned_string_find_permanent(zend_string *str);
+ZEND_API void zend_interned_strings_set_request_storage_handler(zend_new_interned_string_func_t handler);
+ZEND_API void zend_interned_strings_set_permanent_storage_copy_handler(zend_string_copy_storage_func_t handler);
+ZEND_API void zend_interned_strings_switch_storage(void);
+
+ZEND_API extern zend_string  *zend_empty_string;
+ZEND_API extern zend_string  *zend_one_char_string[256];
+ZEND_API extern zend_string **zend_known_strings;
 
 END_EXTERN_C()
 
@@ -56,7 +66,9 @@ END_EXTERN_C()
 
 #define ZSTR_IS_INTERNED(s)                                    (GC_FLAGS(s) & IS_STR_INTERNED)
 
-#define ZSTR_EMPTY_ALLOC()                             CG(empty_string)
+#define ZSTR_EMPTY_ALLOC() zend_empty_string
+#define ZSTR_CHAR(c) zend_one_char_string[c]
+#define ZSTR_KNOWN(idx) zend_known_strings[idx]
 
 #define _ZSTR_HEADER_SIZE XtOffsetOf(zend_string, val)
 
@@ -162,6 +174,13 @@ static zend_always_inline zend_string *zend_string_init(const char *str, size_t
        return ret;
 }
 
+static zend_always_inline zend_string *zend_string_init_interned(const char *str, size_t len, int persistent)
+{
+       zend_string *ret = zend_string_init(str, len, persistent);
+
+       return zend_new_interned_string(ret);
+}
+
 static zend_always_inline zend_string *zend_string_copy(zend_string *s)
 {
        if (!ZSTR_IS_INTERNED(s)) {
@@ -359,27 +378,6 @@ EMPTY_SWITCH_DEFAULT_CASE()
 #endif
 }
 
-#ifdef ZTS
-static zend_always_inline zend_string* zend_zts_interned_string_init(const char *val, size_t len)
-{
-       zend_string *str;
-
-       str = zend_string_init(val, len, 1);
-
-       zend_string_hash_val(str);
-       GC_FLAGS(str) |= IS_STR_INTERNED;
-       return str;
-}
-
-static zend_always_inline void zend_zts_interned_string_free(zend_string **s)
-{
-       if (NULL != *s) {
-               free(*s);
-               *s = NULL;
-       }
-}
-#endif
-
 #define ZEND_KNOWN_STRINGS(_) \
        _(ZEND_STR_FILE,                   "file") \
        _(ZEND_STR_LINE,                   "line") \
@@ -419,8 +417,6 @@ ZEND_KNOWN_STRINGS(_ZEND_STR_ID)
        ZEND_STR_LAST_KNOWN
 } zend_known_string_id;
 
-ZEND_API uint32_t zend_intern_known_strings(const char **strings, uint32_t count);
-
 #endif /* ZEND_STRING_H */
 
 /*
index cbc5804c99c62219fe7ca5ecea6c1fbdf5548b4a..2cf46f699eed823fffc67f1b6c3145072a0175b3 100644 (file)
@@ -1397,7 +1397,7 @@ ZEND_VM_HELPER(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type)
        target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
        retval = zend_hash_find(target_symbol_table, name);
        if (retval == NULL) {
-               if (UNEXPECTED(zend_string_equals(name, CG(known_strings)[ZEND_STR_THIS]))) {
+               if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) {
                        zval *result;
 
 ZEND_VM_C_LABEL(fetch_this):
@@ -1457,7 +1457,7 @@ ZEND_VM_C_LABEL(fetch_this):
        } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
                retval = Z_INDIRECT_P(retval);
                if (Z_TYPE_P(retval) == IS_UNDEF) {
-                       if (UNEXPECTED(zend_string_equals(name, CG(known_strings)[ZEND_STR_THIS]))) {
+                       if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) {
                                ZEND_VM_C_GOTO(fetch_this);
                        }
                        switch (type) {
@@ -5207,7 +5207,7 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
                                if (Z_TYPE_P(expr) != IS_ARRAY) {
                                        object_init(result);
                                        if (Z_TYPE_P(expr) != IS_NULL) {
-                                               expr = zend_hash_add_new(Z_OBJPROP_P(result), CG(known_strings)[ZEND_STR_SCALAR], expr);
+                                               expr = zend_hash_add_new(Z_OBJPROP_P(result), ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
                                                if (OP1_TYPE == IS_CONST) {
                                                        if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
                                                } else {
@@ -6569,7 +6569,7 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
                do {
                        EG(error_reporting) = 0;
                        if (!EG(error_reporting_ini_entry)) {
-                               zend_ini_entry *p = zend_hash_find_ptr(EG(ini_directives), CG(known_strings)[ZEND_STR_ERROR_REPORTING]);
+                               zend_ini_entry *p = zend_hash_find_ptr(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING));
                                if (p) {
                                        EG(error_reporting_ini_entry) = p;
                                } else {
@@ -6581,7 +6581,7 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
                                        ALLOC_HASHTABLE(EG(modified_ini_directives));
                                        zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
                                }
-                               if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), CG(known_strings)[ZEND_STR_ERROR_REPORTING], EG(error_reporting_ini_entry)) != NULL)) {
+                               if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), EG(error_reporting_ini_entry)) != NULL)) {
                                        EG(error_reporting_ini_entry)->orig_value = EG(error_reporting_ini_entry)->value;
                                        EG(error_reporting_ini_entry)->orig_modifiable = EG(error_reporting_ini_entry)->modifiable;
                                        EG(error_reporting_ini_entry)->modified = 1;
index fac8f6e475e4a8b681feb5c4ae96962564a5eb2f..3bdbaa936b5190b61edccc51502873f7de248563 100644 (file)
@@ -1508,7 +1508,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEN
                do {
                        EG(error_reporting) = 0;
                        if (!EG(error_reporting_ini_entry)) {
-                               zend_ini_entry *p = zend_hash_find_ptr(EG(ini_directives), CG(known_strings)[ZEND_STR_ERROR_REPORTING]);
+                               zend_ini_entry *p = zend_hash_find_ptr(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING));
                                if (p) {
                                        EG(error_reporting_ini_entry) = p;
                                } else {
@@ -1520,7 +1520,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEN
                                        ALLOC_HASHTABLE(EG(modified_ini_directives));
                                        zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
                                }
-                               if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), CG(known_strings)[ZEND_STR_ERROR_REPORTING], EG(error_reporting_ini_entry)) != NULL)) {
+                               if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), EG(error_reporting_ini_entry)) != NULL)) {
                                        EG(error_reporting_ini_entry)->orig_value = EG(error_reporting_ini_entry)->value;
                                        EG(error_reporting_ini_entry)->orig_modifiable = EG(error_reporting_ini_entry)->modifiable;
                                        EG(error_reporting_ini_entry)->modified = 1;
@@ -3404,7 +3404,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_O
                                if (Z_TYPE_P(expr) != IS_ARRAY) {
                                        object_init(result);
                                        if (Z_TYPE_P(expr) != IS_NULL) {
-                                               expr = zend_hash_add_new(Z_OBJPROP_P(result), CG(known_strings)[ZEND_STR_SCALAR], expr);
+                                               expr = zend_hash_add_new(Z_OBJPROP_P(result), ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
                                                if (IS_CONST == IS_CONST) {
                                                        if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
                                                } else {
@@ -7029,7 +7029,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
        target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
        retval = zend_hash_find(target_symbol_table, name);
        if (retval == NULL) {
-               if (UNEXPECTED(zend_string_equals(name, CG(known_strings)[ZEND_STR_THIS]))) {
+               if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) {
                        zval *result;
 
 fetch_this:
@@ -7089,7 +7089,7 @@ fetch_this:
        } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
                retval = Z_INDIRECT_P(retval);
                if (Z_TYPE_P(retval) == IS_UNDEF) {
-                       if (UNEXPECTED(zend_string_equals(name, CG(known_strings)[ZEND_STR_THIS]))) {
+                       if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) {
                                goto fetch_this;
                        }
                        switch (type) {
@@ -12639,7 +12639,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC
                                if (Z_TYPE_P(expr) != IS_ARRAY) {
                                        object_init(result);
                                        if (Z_TYPE_P(expr) != IS_NULL) {
-                                               expr = zend_hash_add_new(Z_OBJPROP_P(result), CG(known_strings)[ZEND_STR_SCALAR], expr);
+                                               expr = zend_hash_add_new(Z_OBJPROP_P(result), ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
                                                if (IS_TMP_VAR == IS_CONST) {
                                                        if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
                                                } else {
@@ -16248,7 +16248,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC
                                if (Z_TYPE_P(expr) != IS_ARRAY) {
                                        object_init(result);
                                        if (Z_TYPE_P(expr) != IS_NULL) {
-                                               expr = zend_hash_add_new(Z_OBJPROP_P(result), CG(known_strings)[ZEND_STR_SCALAR], expr);
+                                               expr = zend_hash_add_new(Z_OBJPROP_P(result), ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
                                                if (IS_VAR == IS_CONST) {
                                                        if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
                                                } else {
@@ -33514,7 +33514,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO
                                if (Z_TYPE_P(expr) != IS_ARRAY) {
                                        object_init(result);
                                        if (Z_TYPE_P(expr) != IS_NULL) {
-                                               expr = zend_hash_add_new(Z_OBJPROP_P(result), CG(known_strings)[ZEND_STR_SCALAR], expr);
+                                               expr = zend_hash_add_new(Z_OBJPROP_P(result), ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
                                                if (IS_CV == IS_CONST) {
                                                        if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
                                                } else {
@@ -39301,7 +39301,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
        target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
        retval = zend_hash_find(target_symbol_table, name);
        if (retval == NULL) {
-               if (UNEXPECTED(zend_string_equals(name, CG(known_strings)[ZEND_STR_THIS]))) {
+               if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) {
                        zval *result;
 
 fetch_this:
@@ -39361,7 +39361,7 @@ fetch_this:
        } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
                retval = Z_INDIRECT_P(retval);
                if (Z_TYPE_P(retval) == IS_UNDEF) {
-                       if (UNEXPECTED(zend_string_equals(name, CG(known_strings)[ZEND_STR_THIS]))) {
+                       if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) {
                                goto fetch_this;
                        }
                        switch (type) {
@@ -50071,7 +50071,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
        target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
        retval = zend_hash_find(target_symbol_table, name);
        if (retval == NULL) {
-               if (UNEXPECTED(zend_string_equals(name, CG(known_strings)[ZEND_STR_THIS]))) {
+               if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) {
                        zval *result;
 
 fetch_this:
@@ -50131,7 +50131,7 @@ fetch_this:
        } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
                retval = Z_INDIRECT_P(retval);
                if (Z_TYPE_P(retval) == IS_UNDEF) {
-                       if (UNEXPECTED(zend_string_equals(name, CG(known_strings)[ZEND_STR_THIS]))) {
+                       if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) {
                                goto fetch_this;
                        }
                        switch (type) {
index ff347a96e3a1d95c4067dcf310380882817c6a15..28b5d958f3870094fc2d4e4cc3a81579b0827b8b 100644 (file)
@@ -341,9 +341,6 @@ static inline void accel_unlock_all(void)
 }
 
 /* Interned strings support */
-static zend_string *(*orig_new_interned_string)(zend_string *str);
-static void (*orig_interned_strings_snapshot)(void);
-static void (*orig_interned_strings_restore)(void);
 
 /* O+ disables creation of interned strings by regular PHP compiler, instead,
  * it creates interned strings in shared memory when saves a script.
@@ -354,15 +351,6 @@ static zend_string *accel_new_interned_string_for_php(zend_string *str)
        return str;
 }
 
-static void accel_interned_strings_snapshot_for_php(void)
-{
-}
-
-static void accel_interned_strings_restore_for_php(void)
-{
-}
-
-#ifndef ZTS
 static void accel_interned_strings_restore_state(void)
 {
     uint32_t idx = ZCSG(interned_strings).nNumUsed;
@@ -396,9 +384,7 @@ static void accel_interned_strings_save_state(void)
 {
        ZCSG(interned_strings_saved_top) = ZCSG(interned_strings_top);
 }
-#endif
 
-#ifndef ZTS
 static zend_string *accel_find_interned_string(zend_string *str)
 {
 /* for now interned strings are supported only for non-ZTS build */
@@ -411,6 +397,7 @@ static zend_string *accel_find_interned_string(zend_string *str)
                /* this is already an interned string */
                return str;
        }
+
        if (!ZCG(counted)) {
                if (accel_activate_add() == FAILURE) {
                        return str;
@@ -436,12 +423,9 @@ static zend_string *accel_find_interned_string(zend_string *str)
 
        return NULL;
 }
-#endif
 
 zend_string *accel_new_interned_string(zend_string *str)
 {
-/* for now interned strings are supported only for non-ZTS build */
-#ifndef ZTS
        zend_ulong h;
        uint32_t nIndex;
        uint32_t idx;
@@ -505,28 +489,24 @@ zend_string *accel_new_interned_string(zend_string *str)
        HT_HASH(&ZCSG(interned_strings), nIndex) = HT_IDX_TO_HASH(idx);
        zend_string_release(str);
        return p->key;
-#else
-       return str;
-#endif
 }
 
-#ifndef ZTS
 /* Copy PHP interned strings from PHP process memory into the shared memory */
-static void accel_use_shm_interned_strings(void)
+static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_interned_string)
 {
        uint32_t idx, j;
        Bucket *p, *q;
 
        /* empty string */
-       CG(empty_string) = accel_new_interned_string(CG(empty_string));
+       zend_empty_string = new_interned_string(zend_empty_string);
        for (j = 0; j < 256; j++) {
                char s[2];
                s[0] = j;
                s[1] = 0;
-               CG(one_char_string)[j] = accel_new_interned_string(zend_string_init(s, 1, 0));
+               zend_one_char_string[j] = new_interned_string(zend_string_init(s, 1, 0));
        }
-       for (j = 0; j < CG(known_strings_count); j++) {
-               CG(known_strings)[j] = accel_new_interned_string(CG(known_strings)[j]);
+       for (j = 0; j < ZEND_STR_LAST_KNOWN; j++) {
+               zend_known_strings[j] = new_interned_string(zend_known_strings[j]);
        }
 
        /* function table hash keys */
@@ -534,10 +514,10 @@ static void accel_use_shm_interned_strings(void)
                p = CG(function_table)->arData + idx;
                if (Z_TYPE(p->val) == IS_UNDEF) continue;
                if (p->key) {
-                       p->key = accel_new_interned_string(p->key);
+                       p->key = new_interned_string(p->key);
                }
                if (Z_FUNC(p->val)->common.function_name) {
-                       Z_FUNC(p->val)->common.function_name = accel_new_interned_string(Z_FUNC(p->val)->common.function_name);
+                       Z_FUNC(p->val)->common.function_name = new_interned_string(Z_FUNC(p->val)->common.function_name);
                }
                if (Z_FUNC(p->val)->common.arg_info &&
                    (Z_FUNC(p->val)->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))) { 
@@ -551,7 +531,7 @@ static void accel_use_shm_interned_strings(void)
                        for (i = 0 ; i < num_args; i++) {
                                if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) {
                                        zend_bool allow_null = ZEND_TYPE_ALLOW_NULL(arg_info[i].type);
-                                       arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(accel_new_interned_string(ZEND_TYPE_NAME(arg_info[i].type)), allow_null);
+                                       arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(new_interned_string(ZEND_TYPE_NAME(arg_info[i].type)), allow_null);
                                }
                        }
                }
@@ -566,11 +546,11 @@ static void accel_use_shm_interned_strings(void)
                ce = (zend_class_entry*)Z_PTR(p->val);
 
                if (p->key) {
-                       p->key = accel_new_interned_string(p->key);
+                       p->key = new_interned_string(p->key);
                }
 
                if (ce->name) {
-                       ce->name = accel_new_interned_string(ce->name);
+                       ce->name = new_interned_string(ce->name);
                }
 
                for (j = 0; j < ce->properties_info.nNumUsed; j++) {
@@ -582,11 +562,11 @@ static void accel_use_shm_interned_strings(void)
                        info = (zend_property_info*)Z_PTR(q->val);
 
                        if (q->key) {
-                               q->key = accel_new_interned_string(q->key);
+                               q->key = new_interned_string(q->key);
                        }
 
                        if (info->name) {
-                               info->name = accel_new_interned_string(info->name);
+                               info->name = new_interned_string(info->name);
                        }
                }
 
@@ -594,10 +574,10 @@ static void accel_use_shm_interned_strings(void)
                        q = ce->function_table.arData + j;
                        if (Z_TYPE(q->val) == IS_UNDEF) continue;
                        if (q->key) {
-                               q->key = accel_new_interned_string(q->key);
+                               q->key = new_interned_string(q->key);
                        }
                        if (Z_FUNC(q->val)->common.function_name) {
-                               Z_FUNC(q->val)->common.function_name = accel_new_interned_string(Z_FUNC(q->val)->common.function_name);
+                               Z_FUNC(q->val)->common.function_name = new_interned_string(Z_FUNC(q->val)->common.function_name);
                        }
                }
 
@@ -605,17 +585,23 @@ static void accel_use_shm_interned_strings(void)
                        q = ce->constants_table.arData + j;
                        if (Z_TYPE(q->val) == IS_UNDEF) continue;
                        if (q->key) {
-                               q->key = accel_new_interned_string(q->key);
+                               q->key = new_interned_string(q->key);
                        }
                }
        }
 
        /* constant hash keys */
        for (idx = 0; idx < EG(zend_constants)->nNumUsed; idx++) {
+               zend_constant *c;
+
                p = EG(zend_constants)->arData + idx;
                if (Z_TYPE(p->val) == IS_UNDEF) continue;
                if (p->key) {
-                       p->key = accel_new_interned_string(p->key);
+                       p->key = new_interned_string(p->key);
+               }
+               c = (zend_constant*)Z_PTR(p->val);
+               if (c->name) {
+                       c->name = new_interned_string(c->name);
                }
        }
 
@@ -629,13 +615,70 @@ static void accel_use_shm_interned_strings(void)
                auto_global = (zend_auto_global*)Z_PTR(p->val);;
 
                zend_string_addref(auto_global->name);
-               auto_global->name = accel_new_interned_string(auto_global->name);
+               auto_global->name = new_interned_string(auto_global->name);
+               if (p->key) {
+                       p->key = new_interned_string(p->key);
+               }
+       }
+
+       for (idx = 0; idx < module_registry.nNumUsed; idx++) {
+               p = module_registry.arData + idx;
+
                if (p->key) {
-                       p->key = accel_new_interned_string(p->key);
+                       p->key = new_interned_string(p->key);
                }
        }
 }
-#endif
+
+static zend_string *accel_replace_string_by_shm_permanent(zend_string *str)
+{
+       zend_string *ret = accel_find_interned_string(str);
+
+       if (ret) {
+               zend_string_release(str);
+               return ret;
+       }
+       return str;
+}
+
+static zend_string *accel_replace_string_by_process_permanent(zend_string *str)
+{
+       zend_string *ret = zend_interned_string_find_permanent(str);
+
+       if (ret) {
+               zend_string_release(str);
+               return ret;
+       }
+       ZEND_ASSERT(0);
+       return str;
+}
+
+
+static void accel_use_shm_interned_strings(void)
+{
+       HANDLE_BLOCK_INTERRUPTIONS();
+       SHM_UNPROTECT();
+       zend_shared_alloc_lock();
+
+       if (ZCSG(interned_strings_saved_top) == NULL) {
+               accel_copy_permanent_strings(accel_new_interned_string);
+       } else {
+               accel_copy_permanent_strings(accel_replace_string_by_shm_permanent);
+               if (ZCG(counted)) {
+                       accel_deactivate_sub();
+               }
+       }
+       accel_interned_strings_save_state();
+
+       zend_shared_alloc_unlock();
+       SHM_PROTECT();
+       HANDLE_UNBLOCK_INTERRUPTIONS();
+}
+
+static void accel_use_permanent_interned_strings(void)
+{
+       accel_copy_permanent_strings(accel_replace_string_by_process_permanent);
+}
 
 #ifndef ZEND_WIN32
 static inline void kill_all_lockers(struct flock *mem_usage_check)
@@ -1015,7 +1058,6 @@ char *accel_make_persistent_key(const char *path, int path_length, int *key_len)
                        }
                        cwd = ZSTR_VAL(cwd_str);
                        cwd_len = ZSTR_LEN(cwd_str);
-#ifndef ZTS
                        if (ZCG(cwd_check)) {
                                ZCG(cwd_check) = 0;
                                if ((ZCG(counted) || ZCSG(accelerator_enabled))) {
@@ -1044,7 +1086,6 @@ char *accel_make_persistent_key(const char *path, int path_length, int *key_len)
                                        }
                                }
                        }
-#endif
                }
 
                if (EXPECTED(ZCG(include_path_key_len))) {
@@ -1057,7 +1098,6 @@ char *accel_make_persistent_key(const char *path, int path_length, int *key_len)
                        include_path = ZSTR_VAL(ZCG(include_path));
                        include_path_len = ZSTR_LEN(ZCG(include_path));
 
-#ifndef ZTS
                        if (ZCG(include_path_check)) {
                                ZCG(include_path_check) = 0;
                                if ((ZCG(counted) || ZCSG(accelerator_enabled))) {
@@ -1085,7 +1125,6 @@ char *accel_make_persistent_key(const char *path, int path_length, int *key_len)
                                        }
                                }
                        }
-#endif
                }
 
                /* Calculate key length */
@@ -2174,11 +2213,9 @@ static void accel_activate(void)
                                zend_reset_cache_vars();
                                zend_accel_hash_clean(&ZCSG(hash));
 
-#if !defined(ZTS)
                                if (ZCG(accel_directives).interned_strings_buffer) {
                                        accel_interned_strings_restore_state();
                                }
-#endif
 
                                zend_shared_alloc_restore_state();
                                ZCSG(accelerator_enabled) = ZCSG(cache_status_before_restart);
@@ -2514,7 +2551,6 @@ static int zend_accel_init_shm(void)
        zend_accel_hash_init(&ZCSG(hash), ZCG(accel_directives).max_accelerated_files);
 
        ZCSG(interned_strings_start) = ZCSG(interned_strings_end) = NULL;
-# ifndef ZTS
        zend_hash_init(&ZCSG(interned_strings), (ZCG(accel_directives).interned_strings_buffer * 1024 * 1024) / _ZSTR_STRUCT_SIZE(8 /* average string length */), NULL, NULL, 1);
        if (ZCG(accel_directives).interned_strings_buffer) {
                void *data;
@@ -2531,27 +2567,11 @@ static int zend_accel_init_shm(void)
                HT_HASH_RESET(&ZCSG(interned_strings));
                ZCSG(interned_strings_end)   = ZCSG(interned_strings_start) + (ZCG(accel_directives).interned_strings_buffer * 1024 * 1024);
                ZCSG(interned_strings_top)   = ZCSG(interned_strings_start);
-
-//             orig_interned_strings_start = CG(interned_strings_start);
-//             orig_interned_strings_end = CG(interned_strings_end);
-//             CG(interned_strings_start) = ZCSG(interned_strings_start);
-//             CG(interned_strings_end) = ZCSG(interned_strings_end);
+               ZCSG(interned_strings_saved_top) = NULL;
+               zend_interned_strings_set_permanent_storage_copy_handler(accel_use_shm_interned_strings);
        }
-# endif
-
-       orig_new_interned_string = zend_new_interned_string;
-       orig_interned_strings_snapshot = zend_interned_strings_snapshot;
-       orig_interned_strings_restore = zend_interned_strings_restore;
-       zend_new_interned_string = accel_new_interned_string_for_php;
-       zend_interned_strings_snapshot = accel_interned_strings_snapshot_for_php;
-       zend_interned_strings_restore = accel_interned_strings_restore_for_php;
 
-# ifndef ZTS
-       if (ZCG(accel_directives).interned_strings_buffer) {
-               accel_use_shm_interned_strings();
-               accel_interned_strings_save_state();
-       }
-# endif
+       zend_interned_strings_set_request_storage_handler(accel_new_interned_string_for_php);
 
        zend_reset_cache_vars();
 
@@ -2800,16 +2820,10 @@ static int accel_startup(zend_extension *extension)
                        case SUCCESSFULLY_REATTACHED:
                                zend_shared_alloc_lock();
                                accel_shared_globals = (zend_accel_shared_globals *) ZSMMG(app_shared_globals);
-                               orig_new_interned_string = zend_new_interned_string;
-                               orig_interned_strings_snapshot = zend_interned_strings_snapshot;
-                               orig_interned_strings_restore = zend_interned_strings_restore;
-
-                               zend_new_interned_string = accel_new_interned_string_for_php;
-                               zend_interned_strings_snapshot = accel_interned_strings_snapshot_for_php;
-                               zend_interned_strings_restore = accel_interned_strings_restore_for_php;
-#ifndef ZTS
-                               accel_use_shm_interned_strings();
-#endif
+                               if (ZCG(accel_directives).interned_strings_buffer) {
+                                       zend_interned_strings_set_permanent_storage_copy_handler(accel_use_shm_interned_strings);
+                               }
+                               zend_interned_strings_set_request_storage_handler(accel_new_interned_string_for_php);
                                zend_shared_alloc_unlock();
                                break;
                        case FAILED_REATTACHED:
@@ -2929,25 +2943,16 @@ void accel_shutdown(void)
                return;
        }
 
-       if (ZCG(accel_directives).interned_strings_buffer) {
-#ifndef ZTS
-               zend_hash_clean(CG(auto_globals));
-               zend_hash_clean(CG(function_table));
-               zend_hash_clean(CG(class_table));
-               zend_hash_clean(EG(zend_constants));
+#ifdef HAVE_OPCACHE_FILE_CACHE
+       file_cache_only = ZCG(accel_directives).file_cache_only;
 #endif
+
+       if (!file_cache_only && ZCG(accel_directives).interned_strings_buffer) {
+               accel_use_permanent_interned_strings();
        }
 
        accel_reset_pcre_cache();
 
-       zend_new_interned_string = orig_new_interned_string;
-       zend_interned_strings_snapshot = orig_interned_strings_snapshot;
-       zend_interned_strings_restore = orig_interned_strings_restore;
-
-#ifdef HAVE_OPCACHE_FILE_CACHE
-       file_cache_only = ZCG(accel_directives).file_cache_only;
-#endif
-
        accel_free_ts_resources();
 
        if (!file_cache_only) {
index 7d0f8dc861a50dd4c8fdfc34bb6c71e7f2bc1c1c..59f3765fea5e9de659908f26c7d0079e095abcef 100644 (file)
@@ -279,16 +279,13 @@ static zend_ast *zend_persist_ast(zend_ast *ast)
 
 static void zend_persist_zval(zval *z)
 {
-       zend_uchar flags;
        void *new_ptr;
 
        switch (Z_TYPE_P(z)) {
                case IS_STRING:
                case IS_CONSTANT:
-                       flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
                        zend_accel_store_interned_string(Z_STR_P(z));
-                       Z_GC_FLAGS_P(z) |= flags;
-                       Z_TYPE_FLAGS_P(z) &= ~IS_TYPE_REFCOUNTED;
+                       Z_TYPE_FLAGS_P(z) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
                        break;
                case IS_ARRAY:
                        new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
@@ -473,7 +470,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
                        ZEND_ASSERT(new_name != NULL);
                        op_array->function_name = new_name;
                } else {
-                       zend_accel_store_string(op_array->function_name);
+                       zend_accel_store_interned_string(op_array->function_name);
                }
        }
 
@@ -533,7 +530,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
                                op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment);
                                ZEND_ASSERT(op_array->doc_comment != NULL);
                        } else {
-                               zend_accel_store_string(op_array->doc_comment);
+                               zend_accel_store_interned_string(op_array->doc_comment);
                        }
                } else {
                        if (!already_stored) {
@@ -607,7 +604,7 @@ static void zend_persist_property_info(zval *zv)
        zend_accel_store_interned_string(prop->name);
        if (prop->doc_comment) {
                if (ZCG(accel_directives).save_comments) {
-                       zend_accel_store_string(prop->doc_comment);
+                       zend_accel_store_interned_string(prop->doc_comment);
                } else {
                        if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) {
                                zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment);
@@ -638,7 +635,7 @@ static void zend_persist_class_constant(zval *zv)
                        if (doc_comment) {
                                c->doc_comment = doc_comment;
                        } else {
-                               zend_accel_store_string(c->doc_comment);
+                               zend_accel_store_interned_string(c->doc_comment);
                        }
                } else {
                        zend_string *doc_comment = zend_shared_alloc_get_xlat_entry(c->doc_comment);
@@ -688,7 +685,7 @@ static void zend_persist_class_entry(zval *zv)
                }
                if (ce->info.user.doc_comment) {
                        if (ZCG(accel_directives).save_comments) {
-                               zend_accel_store_string(ce->info.user.doc_comment);
+                               zend_accel_store_interned_string(ce->info.user.doc_comment);
                        } else {
                                if (!zend_shared_alloc_get_xlat_entry(ce->info.user.doc_comment)) {
                                        zend_shared_alloc_register_xlat_entry(ce->info.user.doc_comment, ce->info.user.doc_comment);
@@ -841,7 +838,7 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
        if (key && *key) {
                *key = zend_accel_memdup(*key, key_length + 1);
        }
-       zend_accel_store_string(script->script.filename);
+       zend_accel_store_interned_string(script->script.filename);
 
 #ifdef __SSE2__
        /* Align to 64-byte boundary */
index f169dffad1af45ea081a02707d79303decda5c66..cb7eb11b7ad68ac7d9c83db0e9fe51799e76b7ad 100644 (file)
@@ -83,9 +83,7 @@ static void zend_hash_persist_calc(HashTable *ht, void (*pPersistElement)(zval *
 
                /* persist bucket and key */
                if (p->key) {
-                       zend_uchar flags = GC_FLAGS(p->key) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
                        ADD_INTERNED_STRING(p->key, 1);
-                       GC_FLAGS(p->key) |= flags;
                }
 
                pPersistElement(&p->val);
@@ -120,18 +118,15 @@ static void zend_persist_ast_calc(zend_ast *ast)
 
 static void zend_persist_zval_calc(zval *z)
 {
-       zend_uchar flags;
        uint32_t size;
 
        switch (Z_TYPE_P(z)) {
                case IS_STRING:
                case IS_CONSTANT:
-                       flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
                        ADD_INTERNED_STRING(Z_STR_P(z), 0);
                        if (ZSTR_IS_INTERNED(Z_STR_P(z))) {
                                Z_TYPE_FLAGS_P(z) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
                        }
-                       Z_GC_FLAGS_P(z) |= flags;
                        break;
                case IS_ARRAY:
                        size = zend_shared_memdup_size(Z_ARR_P(z), sizeof(zend_array));
@@ -177,7 +172,7 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array)
                /* already stored */
                if (op_array->function_name) {
                        zend_string *new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name);
-                       if (IS_ACCEL_INTERNED(new_name)) {
+                       if (new_name) {
                                op_array->function_name = new_name;
                        }
                }
index 3b2145d0fdeb971b4373d98862c1de176107d9ea..8b9ad196e40ce5e938250c018985e703ef48f143 100644 (file)
@@ -2813,11 +2813,7 @@ PHP_FUNCTION(range)
                        zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
                        ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
                                for (; low >= high; low -= (unsigned int)lstep) {
-                                       if (CG(one_char_string)[low]) {
-                                               ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
-                                       } else {
-                                               ZVAL_STRINGL(&tmp, (char*)&low, 1);
-                                       }
+                                       ZVAL_INTERNED_STR(&tmp, ZSTR_CHAR(low));
                                        ZEND_HASH_FILL_ADD(&tmp);
                                        if (((signed int)low - lstep) < 0) {
                                                break;
@@ -2833,11 +2829,7 @@ PHP_FUNCTION(range)
                        zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
                        ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
                                for (; low <= high; low += (unsigned int)lstep) {
-                                       if (CG(one_char_string)[low]) {
-                                               ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
-                                       } else {
-                                               ZVAL_STRINGL(&tmp, (char*)&low, 1);
-                                       }
+                                       ZVAL_INTERNED_STR(&tmp, ZSTR_CHAR(low));
                                        ZEND_HASH_FILL_ADD(&tmp);
                                        if (((signed int)low + lstep) > 255) {
                                                break;
@@ -2846,11 +2838,7 @@ PHP_FUNCTION(range)
                        } ZEND_HASH_FILL_END();
                } else {
                        array_init(return_value);
-                       if (CG(one_char_string)[low]) {
-                               ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
-                       } else {
-                               ZVAL_STRINGL(&tmp, (char*)&low, 1);
-                       }
+                       ZVAL_INTERNED_STR(&tmp, ZSTR_CHAR(low));
                        zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
                }
        } else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) {
index c0120e1fc8988ec0b6f4dfb759ea5165d5de824b..4ae3546d512b28ffe85ffa2301cc275e11c90d81 100644 (file)
@@ -2766,13 +2766,7 @@ PHP_FUNCTION(chr)
        ZEND_PARSE_PARAMETERS_END_EX(c = 0);
 
        c &= 0xff;
-       if (CG(one_char_string)[c]) {
-               ZVAL_INTERNED_STR(return_value, CG(one_char_string)[c]);
-       } else {
-               ZVAL_NEW_STR(return_value, zend_string_alloc(1, 0));
-               Z_STRVAL_P(return_value)[0] = (char)c;
-               Z_STRVAL_P(return_value)[1] = '\0';
-       }
+       ZVAL_INTERNED_STR(return_value, ZSTR_CHAR(c));
 }
 /* }}} */
 
@@ -4568,7 +4562,7 @@ PHP_FUNCTION(parse_str)
                symbol_table = zend_rebuild_symbol_table();
                ZVAL_ARR(&tmp, symbol_table);
                sapi_module.treat_data(PARSE_STRING, res, &tmp);
-               if (UNEXPECTED(zend_hash_del(symbol_table, CG(known_strings)[ZEND_STR_THIS]) == SUCCESS)) {
+               if (UNEXPECTED(zend_hash_del(symbol_table, ZSTR_KNOWN(ZEND_STR_THIS)) == SUCCESS)) {
                        zend_throw_error(NULL, "Cannot re-assign $this");
                }
        } else  {
index 4e331ac2c8c089a7653776ae446dbeef95db0d2e..723fd7d49b64e390859e860f47bad9424cb2946b 100644 (file)
@@ -1601,6 +1601,8 @@ int php_request_startup(void)
 {
        int retval = SUCCESS;
 
+       zend_interned_strings_activate();
+
 #ifdef HAVE_DTRACE
        DTRACE_REQUEST_STARTUP(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
 #endif /* HAVE_DTRACE */
@@ -1679,6 +1681,8 @@ int php_request_startup(void)
 {
        int retval = SUCCESS;
 
+       zend_interned_strings_activate();
+
 #if PHP_SIGCHILD
        signal(SIGCHLD, sigchld_handler);
 #endif
@@ -1711,6 +1715,8 @@ int php_request_startup_for_hook(void)
 {
        int retval = SUCCESS;
 
+       zend_interned_strings_activate();
+
 #if PHP_SIGCHLD
        signal(SIGCHLD, sigchld_handler);
 #endif
@@ -1734,8 +1740,8 @@ void php_request_shutdown_for_exec(void *dummy)
 
        /* used to close fd's in the 3..255 range here, but it's problematic
         */
+       zend_interned_strings_deactivate();
        shutdown_memory_manager(1, 1);
-       zend_interned_strings_restore();
 }
 /* }}} */
 
@@ -1778,12 +1784,12 @@ void php_request_shutdown_for_hook(void *dummy)
                php_shutdown_stream_hashes();
        } zend_end_try();
 
+       zend_interned_strings_deactivate();
+
        zend_try {
                shutdown_memory_manager(CG(unclean_shutdown), 0);
        } zend_end_try();
 
-       zend_interned_strings_restore();
-
 #ifdef ZEND_SIGNALS
        zend_try {
                zend_signal_deactivate();
@@ -1891,7 +1897,7 @@ void php_request_shutdown(void *dummy)
        } zend_end_try();
 
        /* 15. Free Willy (here be crashes) */
-       zend_interned_strings_restore();
+       zend_interned_strings_deactivate();
        zend_try {
                shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0);
        } zend_end_try();
@@ -2357,9 +2363,10 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
        module_startup = 0;
 
        shutdown_memory_manager(1, 0);
-       zend_interned_strings_snapshot();
        virtual_cwd_activate();
 
+       zend_interned_strings_switch_storage();
+
        /* we're done */
        return retval;
 }
index ed4b257848fe74edbf917a6f433bc28a94a6ff5c..4f9fabe434a3c909beb89053ed6a38268ae948c9 100644 (file)
@@ -1706,7 +1706,7 @@ PHPAPI int php_register_url_stream_wrapper(const char *protocol, php_stream_wrap
                return FAILURE;
        }
 
-       return zend_hash_str_add_ptr(&url_stream_wrappers_hash, protocol, protocol_len, wrapper) ? SUCCESS : FAILURE;
+       return zend_hash_add_ptr(&url_stream_wrappers_hash, zend_string_init_interned(protocol, protocol_len, 1), wrapper) ? SUCCESS : FAILURE;
 }
 
 PHPAPI int php_unregister_url_stream_wrapper(const char *protocol)
index b45ef3f6845d70ce52452231ec26c57660402726..f6008c22f181c16ac4317ec5280b43d99d273e87 100644 (file)
@@ -811,15 +811,11 @@ static zend_module_entry sapi_phpdbg_module_entry = {
        STANDARD_MODULE_PROPERTIES
 };
 
-static void phpdbg_interned_strings_nothing(void) { }
-
 static inline int php_sapi_phpdbg_module_startup(sapi_module_struct *module) /* {{{ */
 {
        if (php_module_startup(module, &sapi_phpdbg_module_entry, 1) == FAILURE) {
                return FAILURE;
        }
-       /* prevent zend_interned_strings_restore from invalidating our string pointers too early (in phpdbg allocated memory only gets freed after module shutdown) */
-       zend_interned_strings_restore = phpdbg_interned_strings_nothing;
 
        phpdbg_booted = 1;