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, ...);
# 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)
{
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;
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;
}
{
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;
#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;
}
}
+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
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, ...);
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. */
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);
}
/* }}} */
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;
}
/* }}} */
#ifdef ZTS
tsrm_set_new_thread_end_handler(zend_new_thread_end_handler);
+ tsrm_set_shutdown_handler(zend_interned_strings_dtor);
#endif
return SUCCESS;
#endif
zend_destroy_rsrc_list_dtors();
+#ifndef ZTS
zend_interned_strings_dtor();
+#endif
}
/* }}} */
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);
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;
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) {
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);
}
/* }}} */
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 {
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;
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
}
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;
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) {
} 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 */
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;
}
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);
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;
}
/* }}} */
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 &&
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;
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 {
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));
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;
}
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;
}
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);
}
}
/* }}} */
/* {{{ 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)
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);
}
}
/* }}} */
}
#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 */
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);
} 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);
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;
}
/* 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);
}
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);
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;
}
/* }}} */
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);
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));
}
}
? (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)) {
}
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 {
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;
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);
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; }
;
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);
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;
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;
}
}
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;
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 *) ¬, 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++) {
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;
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;
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;
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;
}
#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,
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;
}
/*
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()
#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)
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)) {
#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") \
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 */
/*
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):
} 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) {
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 {
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 {
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;
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 {
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;
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 {
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:
} 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) {
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 {
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 {
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 {
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:
} 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) {
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:
} 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) {
}
/* 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.
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;
{
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 */
/* this is already an interned string */
return str;
}
+
if (!ZCG(counted)) {
if (accel_activate_add() == FAILURE) {
return 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;
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 */
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))) {
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);
}
}
}
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++) {
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);
}
}
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);
}
}
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);
}
}
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)
}
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))) {
}
}
}
-#endif
}
if (EXPECTED(ZCG(include_path_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))) {
}
}
}
-#endif
}
/* Calculate key length */
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);
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;
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();
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:
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) {
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));
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);
}
}
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) {
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);
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);
}
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);
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 */
/* 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);
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));
/* 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;
}
}
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;
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;
} 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) {
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));
}
/* }}} */
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 {
{
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 */
{
int retval = SUCCESS;
+ zend_interned_strings_activate();
+
#if PHP_SIGCHILD
signal(SIGCHLD, sigchld_handler);
#endif
{
int retval = SUCCESS;
+ zend_interned_strings_activate();
+
#if PHP_SIGCHLD
signal(SIGCHLD, sigchld_handler);
#endif
/* 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();
}
/* }}} */
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();
} 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();
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;
}
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)
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;