Pack zend_constant.flags and zend_constant.module_number into reserved space inside zend_constant.value.

This commit is contained in:
Dmitry Stogov 2018-07-26 12:58:07 +03:00
parent 7a41e4c0d0
commit ab8094c666
15 changed files with 68 additions and 60 deletions

View File

@ -25,6 +25,7 @@ PHP 7.3 INTERNALS UPGRADE NOTES
v. php_add[c]slashes
w. zend_class_entry.iterator_funcs
x. Class declaration opcodes (DECLARE_INHERITED_CLASS ...)
y. zend_constant
2. Build system changes
a. Unix build system changes
@ -160,6 +161,11 @@ PHP 7.3 INTERNALS UPGRADE NOTES
- ADD_INTERFACE and ADD_TRAIT don't use run-time cache to keep interface or
trait. These instructions are executed once, and caching is useless.
y. zend_constant.flags and zend_constant.module_number are packed into
reserved space inside zend_constant.value. They should be accessed using
ZEND_CONTANT_FLAGS(), ZEND_CONSTANTS_MODULE_NUMBER() and
ZEND_CONTANT_SET_FLAGS() macros.
========================
2. Build system changes
========================

View File

@ -909,9 +909,9 @@ register_constant:
"define(): Declaration of case-insensitive constants is deprecated");
}
c.flags = case_sensitive; /* non persistent */
/* non persistent */
ZEND_CONSTANT_SET_FLAGS(&c, case_sensitive, PHP_USER_CONSTANT);
c.name = zend_string_copy(name);
c.module_number = PHP_USER_CONSTANT;
if (zend_register_constant(&c) == SUCCESS) {
RETURN_TRUE;
} else {
@ -2145,13 +2145,13 @@ ZEND_FUNCTION(get_defined_constants)
continue;
}
if (val->module_number == PHP_USER_CONSTANT) {
if (ZEND_CONSTANT_MODULE_NUMBER(val) == PHP_USER_CONSTANT) {
module_number = i;
} else if (val->module_number > i || val->module_number < 0) {
} else if (ZEND_CONSTANT_MODULE_NUMBER(val) > i) {
/* should not happen */
continue;
} else {
module_number = val->module_number;
module_number = ZEND_CONSTANT_MODULE_NUMBER(val);
}
if (Z_TYPE(modules[module_number]) == IS_UNDEF) {

View File

@ -1366,7 +1366,7 @@ ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char
static zend_constant *zend_lookup_reserved_const(const char *name, size_t len) /* {{{ */
{
zend_constant *c = zend_hash_find_ptr_lc(EG(zend_constants), name, len);
if (c && !(c->flags & CONST_CS) && (c->flags & CONST_CT_SUBST)) {
if (c && !(ZEND_CONSTANT_FLAGS(c) & CONST_CS) && (ZEND_CONSTANT_FLAGS(c) & CONST_CT_SUBST)) {
return c;
}
return NULL;
@ -1380,9 +1380,9 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i
/* Substitute case-sensitive (or lowercase) constants */
c = zend_hash_find_ptr(EG(zend_constants), name);
if (c && (
((c->flags & CONST_PERSISTENT)
((ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)
&& !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION)
&& (!(c->flags & CONST_NO_FILE_CACHE) || !(CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE)))
&& (!(ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE) || !(CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE)))
|| (Z_TYPE(c->value) < IS_OBJECT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION))
)) {
ZVAL_COPY_OR_DUP(zv, &c->value);

View File

@ -37,7 +37,7 @@ void free_zend_constant(zval *zv)
{
zend_constant *c = Z_PTR_P(zv);
if (!(c->flags & CONST_PERSISTENT)) {
if (!(ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)) {
zval_ptr_dtor_nogc(&c->value);
if (c->name) {
zend_string_release_ex(c->name, 0);
@ -82,7 +82,7 @@ static int clean_module_constant(zval *el, void *arg)
zend_constant *c = (zend_constant *)Z_PTR_P(el);
int module_number = *(int *)arg;
if (c->module_number == module_number) {
if (ZEND_CONSTANT_MODULE_NUMBER(c) == module_number) {
return 1;
} else {
return 0;
@ -151,9 +151,8 @@ ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int
zend_constant c;
ZVAL_NULL(&c.value);
c.flags = flags;
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
c.module_number = module_number;
zend_register_constant(&c);
}
@ -162,9 +161,8 @@ ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, zen
zend_constant c;
ZVAL_BOOL(&c.value, bval);
c.flags = flags;
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
c.module_number = module_number;
zend_register_constant(&c);
}
@ -173,9 +171,8 @@ ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zen
zend_constant c;
ZVAL_LONG(&c.value, lval);
c.flags = flags;
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
c.module_number = module_number;
zend_register_constant(&c);
}
@ -185,9 +182,8 @@ ZEND_API void zend_register_double_constant(const char *name, size_t name_len, d
zend_constant c;
ZVAL_DOUBLE(&c.value, dval);
c.flags = flags;
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
c.module_number = module_number;
zend_register_constant(&c);
}
@ -197,9 +193,8 @@ ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len,
zend_constant c;
ZVAL_STR(&c.value, zend_string_init_interned(strval, strlen, flags & CONST_PERSISTENT));
c.flags = flags;
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
c.module_number = module_number;
zend_register_constant(&c);
}
@ -257,7 +252,7 @@ static inline zend_constant *zend_get_constant_str_impl(const char *name, size_t
char *lcname = do_alloca(name_len + 1, use_heap);
zend_str_tolower_copy(lcname, name, name_len);
if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, name_len)) != NULL) {
if (c->flags & CONST_CS) {
if (ZEND_CONSTANT_FLAGS(c) & CONST_CS) {
c = NULL;
}
} else {
@ -288,7 +283,7 @@ static inline zend_constant *zend_get_constant_impl(zend_string *name)
zv = zend_hash_str_find(EG(zend_constants), lcname, ZSTR_LEN(name));
if (zv != NULL) {
c = Z_PTR_P(zv);
if (c->flags & CONST_CS) {
if (ZEND_CONSTANT_FLAGS(c) & CONST_CS) {
c = NULL;
}
} else {
@ -436,7 +431,7 @@ failure:
/* try lowercase */
zend_str_tolower(lcname + prefix_len + 1, const_name_len);
if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) != NULL) {
if ((c->flags & CONST_CS) != 0) {
if ((ZEND_CONSTANT_FLAGS(c) & CONST_CS) != 0) {
c = NULL;
}
}
@ -465,7 +460,7 @@ failure:
}
if (!(flags & ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK)) {
if (!(c->flags & (CONST_CS|CONST_CT_SUBST)) && is_access_deprecated(c, name)) {
if (!(ZEND_CONSTANT_FLAGS(c) & (CONST_CS|CONST_CT_SUBST)) && is_access_deprecated(c, name)) {
zend_error(E_DEPRECATED,
"Case-insensitive constants are deprecated. "
"The correct casing for this constant is \"%s\"",
@ -479,12 +474,12 @@ failure:
static void* zend_hash_add_constant(HashTable *ht, zend_string *key, zend_constant *c)
{
void *ret;
zend_constant *copy = pemalloc(sizeof(zend_constant), c->flags & CONST_PERSISTENT);
zend_constant *copy = pemalloc(sizeof(zend_constant), ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
memcpy(copy, c, sizeof(zend_constant));
ret = zend_hash_add_ptr(ht, key, copy);
if (!ret) {
pefree(copy, c->flags & CONST_PERSISTENT);
pefree(copy, ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
}
return ret;
}
@ -499,14 +494,14 @@ ZEND_API int zend_register_constant(zend_constant *c)
printf("Registering constant for module %d\n", c->module_number);
#endif
if (!(c->flags & CONST_CS)) {
lowercase_name = zend_string_tolower_ex(c->name, c->flags & CONST_PERSISTENT);
if (!(ZEND_CONSTANT_FLAGS(c) & CONST_CS)) {
lowercase_name = zend_string_tolower_ex(c->name, ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
lowercase_name = zend_new_interned_string(lowercase_name);
name = lowercase_name;
} else {
char *slash = strrchr(ZSTR_VAL(c->name), '\\');
if (slash) {
lowercase_name = zend_string_init(ZSTR_VAL(c->name), ZSTR_LEN(c->name), c->flags & CONST_PERSISTENT);
lowercase_name = zend_string_init(ZSTR_VAL(c->name), ZSTR_LEN(c->name), ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
zend_str_tolower(ZSTR_VAL(lowercase_name), slash - ZSTR_VAL(c->name));
lowercase_name = zend_new_interned_string(lowercase_name);
name = lowercase_name;
@ -525,7 +520,7 @@ ZEND_API int zend_register_constant(zend_constant *c)
}
zend_error(E_NOTICE,"Constant %s already defined", ZSTR_VAL(name));
zend_string_release(c->name);
if (!(c->flags & CONST_PERSISTENT)) {
if (!(ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)) {
zval_ptr_dtor_nogc(&c->value);
}
ret = FAILURE;

View File

@ -27,7 +27,7 @@
#define CONST_CT_SUBST (1<<2) /* Allow compile-time substitution */
#define CONST_NO_FILE_CACHE (1<<3) /* Can't be saved in file cache */
#define PHP_USER_CONSTANT INT_MAX /* a constant defined in user space */
#define PHP_USER_CONSTANT 0x7fffff /* a constant defined in user space */
/* Flag for zend_get_constant_ex(). Must not class with ZEND_FETCH_CLASS_* flags. */
#define ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK 0x1000
@ -35,10 +35,19 @@
typedef struct _zend_constant {
zval value;
zend_string *name;
int flags;
int module_number;
} zend_constant;
#define ZEND_CONSTANT_FLAGS(c) \
(Z_CONSTANT_FLAGS((c)->value) & 0xff)
#define ZEND_CONSTANT_MODULE_NUMBER(c) \
(Z_CONSTANT_FLAGS((c)->value) >> 8)
#define ZEND_CONSTANT_SET_FLAGS(c, _flags, _module_number) do { \
Z_CONSTANT_FLAGS((c)->value) = \
((_flags) & 0xff) | ((_module_number) << 8); \
} while (0)
#define REGISTER_NULL_CONSTANT(name, flags) zend_register_null_constant((name), sizeof(name)-1, (flags), module_number)
#define REGISTER_BOOL_CONSTANT(name, bval, flags) zend_register_bool_constant((name), sizeof(name)-1, (bval), (flags), module_number)
#define REGISTER_LONG_CONSTANT(name, lval, flags) zend_register_long_constant((name), sizeof(name)-1, (lval), (flags), module_number)

View File

@ -3296,7 +3296,7 @@ static zend_always_inline int _zend_quick_get_constant(
} else {
key++;
zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1);
if (zv && (((zend_constant*)Z_PTR_P(zv))->flags & CONST_CS) == 0) {
if (zv && (ZEND_CONSTANT_FLAGS((zend_constant*)Z_PTR_P(zv)) & CONST_CS) == 0) {
c = (zend_constant*)Z_PTR_P(zv);
} else {
if ((flags & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
@ -3307,7 +3307,7 @@ static zend_always_inline int _zend_quick_get_constant(
} else {
key++;
zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1);
if (zv && (((zend_constant*)Z_PTR_P(zv))->flags & CONST_CS) == 0) {
if (zv && (ZEND_CONSTANT_FLAGS((zend_constant*)Z_PTR_P(zv)) & CONST_CS) == 0) {
c = (zend_constant*)Z_PTR_P(zv);
}
}
@ -3339,7 +3339,7 @@ static zend_always_inline int _zend_quick_get_constant(
if (!check_defined_only) {
ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value);
if (!(c->flags & (CONST_CS|CONST_CT_SUBST))) {
if (!(ZEND_CONSTANT_FLAGS(c) & (CONST_CS|CONST_CT_SUBST))) {
const char *ns_sep;
size_t shortname_offset;
size_t shortname_len;

View File

@ -101,7 +101,7 @@ static void zend_extension_deactivator(zend_extension *extension) /* {{{ */
static int clean_non_persistent_constant_full(zval *zv) /* {{{ */
{
zend_constant *c = Z_PTR_P(zv);
return (c->flags & CONST_PERSISTENT) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
return (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
}
/* }}} */
@ -319,7 +319,7 @@ void shutdown_executor(void) /* {{{ */
} else {
ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) {
zend_constant *c = Z_PTR_P(zv);
if (c->flags & CONST_PERSISTENT) {
if (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) {
break;
}
zval_ptr_dtor_nogc(&c->value);

View File

@ -203,6 +203,7 @@ struct _zval_struct {
uint32_t fe_iter_idx; /* foreach iterator index */
uint32_t access_flags; /* class constant access flags */
uint32_t property_guard; /* single property guard */
uint32_t constant_flags; /* constant flags */
uint32_t extra; /* not further specified */
} u2;
};
@ -449,6 +450,9 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
#define Z_PROPERTY_GUARD(zval) (zval).u2.property_guard
#define Z_PROPERTY_GUARD_P(zval_p) Z_PROPERTY_GUARD(*(zval_p))
#define Z_CONSTANT_FLAGS(zval) (zval).u2.constant_flags
#define Z_CONSTANT_FLAGS_P(zval_p) Z_CONSTANT_FLAGS(*(zval_p))
#define Z_EXTRA(zval) (zval).u2.extra
#define Z_EXTRA_P(zval_p) Z_EXTRA(*(zval_p))

View File

@ -7039,9 +7039,9 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
HANDLE_EXCEPTION();
}
}
c.flags = CONST_CS; /* non persistent, case sensitive */
/* non persistent, case sensitive */
ZEND_CONSTANT_SET_FLAGS(&c, CONST_CS, PHP_USER_CONSTANT);
c.name = zend_string_copy(Z_STR_P(name));
c.module_number = PHP_USER_CONSTANT;
if (zend_register_constant(&c) == FAILURE) {
}

View File

@ -5918,9 +5918,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST
HANDLE_EXCEPTION();
}
}
c.flags = CONST_CS; /* non persistent, case sensitive */
/* non persistent, case sensitive */
ZEND_CONSTANT_SET_FLAGS(&c, CONST_CS, PHP_USER_CONSTANT);
c.name = zend_string_copy(Z_STR_P(name));
c.module_number = PHP_USER_CONSTANT;
if (zend_register_constant(&c) == FAILURE) {
}

View File

@ -44,7 +44,7 @@ int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int
zend_str_tolower(lookup_name, ZSTR_LEN(name));
if ((c = zend_hash_str_find_ptr(EG(zend_constants), lookup_name, ZSTR_LEN(name))) != NULL) {
if (!(c->flags & CONST_CT_SUBST) || (c->flags & CONST_CS)) {
if (!(ZEND_CONSTANT_FLAGS(c) & CONST_CT_SUBST) || (ZEND_CONSTANT_FLAGS(c) & CONST_CS)) {
retval = 0;
}
} else {
@ -54,8 +54,8 @@ int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int
}
if (retval) {
if ((c->flags & CONST_PERSISTENT)
&& (!(c->flags & CONST_NO_FILE_CACHE)
if ((ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)
&& (!(ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE)
|| !(CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) {
ZVAL_COPY_VALUE(result, &c->value);
if (copy) {

View File

@ -926,7 +926,7 @@ static int _extension_const_string(zval *el, int num_args, va_list args, zend_ha
struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
int *num_classes = va_arg(args, int*);
if (constant->module_number == module->module_number) {
if (ZEND_CONSTANT_MODULE_NUMBER(constant) == module->module_number) {
_const_string(str, ZSTR_VAL(constant->name), &constant->value, indent);
(*num_classes)++;
}
@ -5696,7 +5696,7 @@ static int _addconstant(zval *el, int num_args, va_list args, zend_hash_key *has
zval *retval = va_arg(args, zval*);
int number = va_arg(args, int);
if (number == constant->module_number) {
if (number == ZEND_CONSTANT_MODULE_NUMBER(constant)) {
ZVAL_COPY_OR_DUP(&const_val, &constant->value);
zend_hash_update(Z_ARRVAL_P(retval), constant->name, &const_val);
}

View File

@ -581,19 +581,16 @@ static void cli_register_file_handles(void) /* {{{ */
php_stream_to_zval(s_out, &oc.value);
php_stream_to_zval(s_err, &ec.value);
ic.flags = CONST_CS;
ZEND_CONSTANT_SET_FLAGS(&ic, CONST_CS, 0);
ic.name = zend_string_init_interned("STDIN", sizeof("STDIN")-1, 0);
ic.module_number = 0;
zend_register_constant(&ic);
oc.flags = CONST_CS;
ZEND_CONSTANT_SET_FLAGS(&oc, CONST_CS, 0);
oc.name = zend_string_init_interned("STDOUT", sizeof("STDOUT")-1, 0);
oc.module_number = 0;
zend_register_constant(&oc);
ec.flags = CONST_CS;
ZEND_CONSTANT_SET_FLAGS(&ec, CONST_CS, 0);
ec.name = zend_string_init_interned("STDERR", sizeof("STDERR")-1, 0);
ec.module_number = 0;
zend_register_constant(&ec);
}
/* }}} */

View File

@ -1013,23 +1013,20 @@ void phpdbg_register_file_handles(void) /* {{{ */
php_stream_to_zval(s_err, &zerr);
ic.value = zin;
ic.flags = CONST_CS;
ZEND_CONSTANT_SET_FLAGS(&ic, CONST_CS, 0);
ic.name = zend_string_init(ZEND_STRL("STDIN"), 0);
ic.module_number = 0;
zend_hash_del(EG(zend_constants), ic.name);
zend_register_constant(&ic);
oc.value = zout;
oc.flags = CONST_CS;
ZEND_CONSTANT_SET_FLAGS(&oc, CONST_CS, 0);
oc.name = zend_string_init(ZEND_STRL("STDOUT"), 0);
oc.module_number = 0;
zend_hash_del(EG(zend_constants), oc.name);
zend_register_constant(&oc);
ec.value = zerr;
ec.flags = CONST_CS;
ZEND_CONSTANT_SET_FLAGS(&ec, CONST_CS, 0);
ec.name = zend_string_init(ZEND_STRL("STDERR"), 0);
ec.module_number = 0;
zend_hash_del(EG(zend_constants), ec.name);
zend_register_constant(&ec);
}

View File

@ -105,7 +105,7 @@ PHPDBG_INFO(constants) /* {{{ */
if (EG(zend_constants)) {
phpdbg_try_access {
ZEND_HASH_FOREACH_PTR(EG(zend_constants), data) {
if (data->module_number == PHP_USER_CONSTANT) {
if (ZEND_CONSTANT_MODULE_NUMBER(data) == PHP_USER_CONSTANT) {
zend_hash_update_ptr(&consts, data->name, data);
}
} ZEND_HASH_FOREACH_END();