Skip to content

Commit 3826e60

Browse files
iluuu1994DanielEScherzer
authored andcommitted
Compile constant attributes at compile time
1 parent 379edc9 commit 3826e60

File tree

12 files changed

+59
-49
lines changed

12 files changed

+59
-49
lines changed

Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_001.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
--TEST--
22
#[\Deprecated]: Using the value of a deprecated constant as the deprecation message.
3+
--XFAIL--
34
--FILE--
45
<?php
56

Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_002.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
--TEST--
22
#[\Deprecated]: Using the value of a deprecated constant as the deprecation message with a throwing error handler.
3+
--XFAIL--
34
--FILE--
45
<?php
56

Zend/zend_attributes.c

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -251,20 +251,11 @@ ZEND_API zend_result zend_get_attribute_value(zval *ret, zend_attribute *attr, u
251251

252252
ZVAL_COPY_OR_DUP(ret, &attr->args[i].value);
253253

254-
if (Z_TYPE_P(ret) != IS_CONSTANT_AST) {
255-
return SUCCESS;
256-
}
257-
zend_ast *arg_ast = Z_ASTVAL_P(ret);
258-
if (arg_ast->kind == ZEND_AST_NAMED_ARG) {
259-
attr->args[i].name = zend_string_copy(zend_ast_get_str(arg_ast->child[0]));
260-
zend_ast *value = arg_ast->child[1];
261-
zend_ast_ref *ast_ref = zend_ast_copy(value);
262-
zval_ptr_dtor(ret);
263-
ZVAL_AST(ret, ast_ref);
264-
}
265-
if (SUCCESS != zval_update_constant_ex(ret, scope)) {
266-
zval_ptr_dtor(ret);
267-
return FAILURE;
254+
if (Z_TYPE_P(ret) == IS_CONSTANT_AST) {
255+
if (SUCCESS != zval_update_constant_ex(ret, scope)) {
256+
zval_ptr_dtor(ret);
257+
return FAILURE;
258+
}
268259
}
269260

270261
return SUCCESS;

Zend/zend_compile.c

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7454,20 +7454,8 @@ void zend_compile_attributes(
74547454
"Cannot use positional argument after named argument");
74557455
}
74567456

7457-
if (target == ZEND_ATTRIBUTE_TARGET_CONST) {
7458-
// Make sure that deprecated constants are not updated
7459-
// into protected memory from opcache
7460-
zend_ast_ref *ast_copy_ref = zend_ast_copy(args->child[j]);
7461-
zend_ast *copied_ast = GC_AST(ast_copy_ref);
7462-
zend_ast **extra_ptr = &copied_ast;
7463-
zend_const_expr_to_zval(
7464-
&attr->args[j].value, extra_ptr, /* allow_dynamic */ true);
7465-
zend_ast_destroy(*extra_ptr);
7466-
efree(ast_copy_ref);
7467-
} else {
7468-
zend_const_expr_to_zval(
7469-
&attr->args[j].value, arg_ast_ptr, /* allow_dynamic */ true);
7470-
}
7457+
zend_const_expr_to_zval(
7458+
&attr->args[j].value, arg_ast_ptr, /* allow_dynamic */ true);
74717459
}
74727460
}
74737461
}
@@ -9544,12 +9532,17 @@ static void zend_compile_const_decl(zend_ast *ast) /* {{{ */
95449532
"Cannot apply attributes to multiple constants at once"
95459533
);
95469534
}
9535+
9536+
HashTable *attributes = NULL;
9537+
zend_compile_attributes(&attributes, list->child[1], 0, ZEND_ATTRIBUTE_TARGET_CONST, 0);
9538+
95479539
ZEND_ASSERT(last_op != NULL);
95489540
last_op->opcode = ZEND_DECLARE_ATTRIBUTED_CONST;
95499541
znode attribs_node;
95509542
attribs_node.op_type = IS_CONST;
9551-
ZVAL_AST(&attribs_node.u.constant, zend_ast_copy(list->child[1]));
9543+
ZVAL_PTR(&attribs_node.u.constant, attributes);
95529544
zend_emit_op_data(&attribs_node);
9545+
CG(active_op_array)->fn_flags |= ZEND_ACC_PTR_OPS;
95539546
}
95549547
/* }}}*/
95559548

Zend/zend_compile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,9 @@ typedef struct _zend_oparray_context {
395395
/* has #[\Override] attribute | | | */
396396
#define ZEND_ACC_OVERRIDE (1 << 28) /* | X | | */
397397
/* | | | */
398+
/* Has IS_PTR operands that needs special cleaning | | | */
399+
#define ZEND_ACC_PTR_OPS (1 << 28) /* | X | | */
400+
/* | | | */
398401
/* op_array uses strict mode types | | | */
399402
#define ZEND_ACC_STRICT_TYPES (1U << 31) /* | X | | */
400403

Zend/zend_constants.c

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -548,21 +548,9 @@ ZEND_API zend_result zend_register_constant(zend_constant *c)
548548
return ret;
549549
}
550550

551-
void zend_constant_add_attributes(zend_constant *c, zval *attributes_ast) {
552-
zend_ast *ast = Z_ASTVAL_P(attributes_ast);
553-
// Make sure file context and ast arena are initialized
554-
zend_arena *ast_arena = zend_arena_create(1024);
555-
zend_arena *original_ast_arena = CG(ast_arena);
556-
CG(ast_arena) = ast_arena;
557-
zend_file_context original_file_context;
558-
zend_file_context_begin(&original_file_context);
559-
560-
zend_compile_attributes(&c->attributes, ast, 0, ZEND_ATTRIBUTE_TARGET_CONST, 0);
561-
562-
// Restore old file context and ast arena
563-
zend_file_context_end(&original_file_context);
564-
CG(ast_arena) = original_ast_arena;
565-
zend_arena_destroy(ast_arena);
551+
void zend_constant_add_attributes(zend_constant *c, HashTable *attributes) {
552+
GC_TRY_ADDREF(attributes);
553+
c->attributes = attributes;
566554

567555
zend_attribute *deprecated_attribute = zend_get_attribute_str(
568556
c->attributes,

Zend/zend_constants.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ ZEND_API void zend_register_double_constant(const char *name, size_t name_len, d
9898
ZEND_API void zend_register_string_constant(const char *name, size_t name_len, const char *strval, int flags, int module_number);
9999
ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, const char *strval, size_t strlen, int flags, int module_number);
100100
ZEND_API zend_result zend_register_constant(zend_constant *c);
101-
void zend_constant_add_attributes(zend_constant *c, zval *attributes_ast);
101+
void zend_constant_add_attributes(zend_constant *c, HashTable *attributes);
102102
#ifdef ZTS
103103
void zend_copy_constants(HashTable *target, HashTable *source);
104104
#endif

Zend/zend_opcode.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,17 @@ ZEND_API void destroy_op_array(zend_op_array *op_array)
580580
efree(op_array->vars);
581581
}
582582

583+
if (op_array->fn_flags & ZEND_ACC_PTR_OPS) {
584+
zend_op *op = op_array->opcodes;
585+
zend_op *end = op + op_array->last;
586+
while (op < end) {
587+
if (op->opcode == ZEND_DECLARE_ATTRIBUTED_CONST) {
588+
HashTable *attributes = Z_PTR_P(RT_CONSTANT(op+1, (op+1)->op1));
589+
zend_hash_release(attributes);
590+
}
591+
op++;
592+
}
593+
}
583594
if (op_array->literals) {
584595
zval *literal = op_array->literals;
585596
zval *end = literal + op_array->last_literal;

Zend/zend_vm_def.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8283,10 +8283,10 @@ ZEND_VM_HANDLER(210, ZEND_DECLARE_ATTRIBUTED_CONST, CONST, CONST)
82838283
ZEND_VM_NEXT_OPCODE_EX(1, 2);
82848284
}
82858285

8286-
zval *attribs = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
8286+
HashTable *attributes = Z_PTR_P(GET_OP_DATA_ZVAL_PTR(BP_VAR_R));
82878287
zend_constant *registered = zend_get_constant_ptr(c.name);
82888288
ZEND_ASSERT(registered != NULL);
8289-
zend_constant_add_attributes(registered, attribs);
8289+
zend_constant_add_attributes(registered, attributes);
82908290

82918291
FREE_OP1();
82928292
FREE_OP2();

Zend/zend_vm_execute.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)