12
12
#include "zend_language_scanner_defs.h"
13
13
#include "zend_language_parser.h"
14
14
#include "zend_exceptions.h"
15
+ #include "zend_hash.h"
15
16
#include "zend_smart_str.h"
16
17
#if PHP_VERSION_ID >= 80200
17
18
/* Used for AllowDynamicProperties */
18
19
#include "zend_attributes.h"
19
20
#endif
20
21
22
+ #ifndef ZEND_THIS
23
+ #define ZEND_THIS getThis()
24
+ #endif
25
+
21
26
#ifndef ZEND_ARG_INFO_WITH_DEFAULT_VALUE
22
27
#define ZEND_ARG_INFO_WITH_DEFAULT_VALUE (pass_by_ref , name , default_value ) \
23
28
ZEND_ARG_INFO(pass_by_ref, name)
50
55
#define ast_register_flag_constant (name , value ) \
51
56
REGISTER_NS_LONG_CONSTANT("ast\\flags", name, value, CONST_CS | CONST_PERSISTENT)
52
57
53
- // The number of cache slots there are must be the same as AST_NUM_CACHE_SLOTS in php_ast.h
54
- #define AST_CACHE_SLOT_KIND &AST_G(cache_slots)[3 * 0]
55
- #define AST_CACHE_SLOT_FLAGS &AST_G(cache_slots)[3 * 1]
56
- #define AST_CACHE_SLOT_LINENO &AST_G(cache_slots)[3 * 2]
57
- #define AST_CACHE_SLOT_CHILDREN &AST_G(cache_slots)[3 * 3]
58
+ // These are in the order the properties were declared with ast_declare_property.
59
+ #define AST_NODE_PROP_KIND (object ) OBJ_PROP_NUM((object), 0)
60
+ #define AST_NODE_PROP_FLAGS (object ) OBJ_PROP_NUM((object), 1)
61
+ #define AST_NODE_PROP_LINENO (object ) OBJ_PROP_NUM((object), 2)
62
+ #define AST_NODE_PROP_CHILDREN (object ) OBJ_PROP_NUM((object), 3)
63
+
64
+ #define AST_NODE_SET_PROP_KIND (object , num ) ZVAL_LONG(AST_NODE_PROP_KIND((object)), (num))
65
+ #define AST_NODE_SET_PROP_FLAGS (object , num ) ZVAL_LONG(AST_NODE_PROP_FLAGS((object)), (num))
66
+ #define AST_NODE_SET_PROP_LINENO (object , num ) ZVAL_LONG(AST_NODE_PROP_LINENO((object)), (num))
67
+ // Set the ast\Node->children array to the given reference-counted array without incrementing the reference count of the array.
68
+ // Do not use this macro with immutable arrays.
69
+ #define AST_NODE_SET_PROP_CHILDREN_ARRAY (object , array ) ZVAL_ARR(AST_NODE_PROP_CHILDREN((object)), (array))
70
+
71
+ #define AST_METADATA_PROP_KIND (object ) OBJ_PROP_NUM((object), 0)
72
+ #define AST_METADATA_PROP_NAME (object ) OBJ_PROP_NUM((object), 1)
73
+ #define AST_METADATA_PROP_FLAGS (object ) OBJ_PROP_NUM((object), 2)
74
+ #define AST_METADATA_PROP_FLAGS_COMBINABLE (object ) OBJ_PROP_NUM((object), 3)
58
75
59
76
#define AST_CURRENT_VERSION 90
60
77
@@ -334,22 +351,20 @@ static const ast_flag_info flag_info[] = {
334
351
{ ZEND_AST_CONDITIONAL , 1 , conditional_flags },
335
352
};
336
353
337
- // NOTE(tandre) in php 8, to get a writeable pointer to a property, OBJ_PROP_NUM(AST_CACHE_SLOT_PROPNAME) can be used.
338
-
339
- static inline void ast_update_property (zval * object , zend_string * name , zval * value , void * * cache_slot ) {
354
+ static inline void ast_update_property (zval * object , zend_string * name , zval * value ) {
340
355
#if PHP_VERSION_ID < 80000
341
356
zval name_zv ;
342
357
ZVAL_STR (& name_zv , name );
343
- Z_OBJ_HT_P (object )-> write_property (object , & name_zv , value , cache_slot );
358
+ Z_OBJ_HT_P (object )-> write_property (object , & name_zv , value , NULL );
344
359
#else
345
- Z_OBJ_HT_P (object )-> write_property (Z_OBJ_P (object ), name , value , cache_slot );
360
+ Z_OBJ_HT_P (object )-> write_property (Z_OBJ_P (object ), name , value , NULL );
346
361
#endif
347
362
}
348
363
349
- static inline void ast_update_property_long (zval * object , zend_string * name , zend_long value_raw , void * * cache_slot ) {
364
+ static inline void ast_update_property_long (zval * object , zend_string * name , zend_long value_raw ) {
350
365
zval value_zv ;
351
366
ZVAL_LONG (& value_zv , value_raw );
352
- ast_update_property (object , name , & value_zv , cache_slot );
367
+ ast_update_property (object , name , & value_zv );
353
368
}
354
369
355
370
static zend_ast * get_ast (zend_string * code , zend_arena * * ast_arena , zend_string * filename ) {
@@ -617,30 +632,28 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state);
617
632
static void ast_create_virtual_node_ex (
618
633
zval * zv , zend_ast_kind kind , zend_ast_attr attr , uint32_t lineno ,
619
634
ast_state_info_t * state , uint32_t num_children , ...) {
620
- zval tmp_zv ;
621
635
va_list va ;
622
636
uint32_t i ;
623
637
624
638
object_init_ex (zv , ast_node_ce );
625
639
626
- ast_update_property_long (zv , AST_STR (str_kind ), kind , AST_CACHE_SLOT_KIND );
627
-
628
- ast_update_property_long (zv , AST_STR (str_flags ), attr , AST_CACHE_SLOT_FLAGS );
640
+ zend_object * obj = Z_OBJ_P (zv );
629
641
630
- ast_update_property_long (zv , AST_STR (str_lineno ), lineno , AST_CACHE_SLOT_LINENO );
642
+ AST_NODE_SET_PROP_KIND (obj , kind );
643
+ AST_NODE_SET_PROP_FLAGS (obj , attr );
644
+ AST_NODE_SET_PROP_LINENO (obj , lineno );
631
645
632
- array_init_size (& tmp_zv , num_children );
633
- Z_DELREF (tmp_zv );
634
- ast_update_property (zv , AST_STR (str_children ), & tmp_zv , AST_CACHE_SLOT_CHILDREN );
646
+ array_init_size (AST_NODE_PROP_CHILDREN (obj ), num_children );
647
+ HashTable * children = Z_ARRVAL_P (AST_NODE_PROP_CHILDREN (obj ));
635
648
636
649
va_start (va , num_children );
637
650
for (i = 0 ; i < num_children ; i ++ ) {
638
651
zval * child_zv = va_arg (va , zval * );
639
652
zend_string * child_name = ast_kind_child_name (kind , i );
640
653
if (child_name ) {
641
- zend_hash_add_new (Z_ARRVAL ( tmp_zv ) , child_name , child_zv );
654
+ zend_hash_add_new (children , child_name , child_zv );
642
655
} else {
643
- zend_hash_next_index_insert (Z_ARRVAL ( tmp_zv ) , child_zv );
656
+ zend_hash_next_index_insert (children , child_zv );
644
657
}
645
658
}
646
659
va_end (va );
@@ -870,7 +883,7 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t
870
883
}
871
884
872
885
static void ast_to_zval (zval * zv , zend_ast * ast , ast_state_info_t * state ) {
873
- zval tmp_zv , children_zv ;
886
+ zval tmp_zv ;
874
887
875
888
if (ast == NULL ) {
876
889
ZVAL_NULL (zv );
@@ -939,7 +952,7 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) {
939
952
ast_to_zval (zv , ast -> child [1 ], state );
940
953
// The property visibility is on the AST_PROP_GROUP node.
941
954
// Add it to the AST_PROP_DECL node for old
942
- ast_update_property_long ( zv , AST_STR ( str_flags ), ast -> attr , AST_CACHE_SLOT_FLAGS );
955
+ AST_NODE_SET_PROP_FLAGS ( Z_OBJ_P ( zv ), ast -> attr );
943
956
return ;
944
957
}
945
958
break ;
@@ -1007,48 +1020,50 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) {
1007
1020
1008
1021
object_init_ex (zv , ast_node_ce );
1009
1022
1010
- ast_update_property_long (zv , AST_STR (str_kind ), ast -> kind , AST_CACHE_SLOT_KIND );
1023
+ zend_object * obj = Z_OBJ_P (zv );
1024
+
1025
+ AST_NODE_SET_PROP_KIND (obj , ast -> kind );
1011
1026
1012
- ast_update_property_long ( zv , AST_STR ( str_lineno ), zend_ast_get_lineno (ast ), AST_CACHE_SLOT_LINENO );
1027
+ AST_NODE_SET_PROP_LINENO ( obj , zend_ast_get_lineno (ast ));
1013
1028
1014
- array_init (& children_zv );
1015
- Z_DELREF (children_zv );
1016
- ast_update_property (zv , AST_STR (str_children ), & children_zv , AST_CACHE_SLOT_CHILDREN );
1029
+ array_init (AST_NODE_PROP_CHILDREN (obj ));
1030
+ HashTable * children = Z_ARRVAL_P (AST_NODE_PROP_CHILDREN (obj ));
1017
1031
1018
1032
if (ast_kind_is_decl (ast -> kind )) {
1019
1033
zend_ast_decl * decl = (zend_ast_decl * ) ast ;
1020
1034
1021
- ast_update_property_long ( zv , AST_STR ( str_flags ), decl -> flags , AST_CACHE_SLOT_FLAGS );
1035
+ AST_NODE_SET_PROP_FLAGS ( obj , decl -> flags );
1022
1036
1023
- ast_update_property_long (zv , AST_STR (str_endLineno ), decl -> end_lineno , NULL );
1037
+ // This is an undeclared dynamic property and has no cache slot.
1038
+ ast_update_property_long (zv , AST_STR (str_endLineno ), decl -> end_lineno );
1024
1039
1025
1040
if (decl -> name ) {
1026
1041
ZVAL_STR (& tmp_zv , decl -> name );
1042
+ Z_TRY_ADDREF (tmp_zv );
1027
1043
} else {
1028
1044
ZVAL_NULL (& tmp_zv );
1029
1045
}
1030
1046
1031
- Z_TRY_ADDREF (tmp_zv );
1032
- zend_hash_add_new (Z_ARRVAL (children_zv ), AST_STR (str_name ), & tmp_zv );
1047
+ zend_hash_add_new (children , AST_STR (str_name ), & tmp_zv );
1033
1048
1034
1049
if (decl -> doc_comment ) {
1035
1050
ZVAL_STR (& tmp_zv , decl -> doc_comment );
1051
+ Z_TRY_ADDREF (tmp_zv );
1036
1052
} else {
1037
1053
ZVAL_NULL (& tmp_zv );
1038
1054
}
1039
1055
1040
- Z_TRY_ADDREF (tmp_zv );
1041
- zend_hash_add_new (Z_ARRVAL (children_zv ), AST_STR (str_docComment ), & tmp_zv );
1056
+ zend_hash_add_new (children , AST_STR (str_docComment ), & tmp_zv );
1042
1057
} else {
1043
1058
#if PHP_VERSION_ID < 70100
1044
1059
if (ast -> kind == ZEND_AST_CLASS_CONST_DECL ) {
1045
1060
ast -> attr = ZEND_ACC_PUBLIC ;
1046
1061
}
1047
1062
#endif
1048
- ast_update_property_long ( zv , AST_STR ( str_flags ), ast -> attr , AST_CACHE_SLOT_FLAGS );
1063
+ AST_NODE_SET_PROP_FLAGS ( obj , ast -> attr );
1049
1064
}
1050
1065
1051
- ast_fill_children_ht (Z_ARRVAL ( children_zv ) , ast , state );
1066
+ ast_fill_children_ht (children , ast , state );
1052
1067
#if PHP_VERSION_ID < 70400
1053
1068
if (ast -> kind == ZEND_AST_PROP_DECL && state -> version >= 70 ) {
1054
1069
zval type_zval ;
@@ -1064,7 +1079,7 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) {
1064
1079
ast_create_virtual_node_ex (
1065
1080
zv , ZEND_AST_PROP_GROUP , ast -> attr , zend_ast_get_lineno (ast ), state , 2 , & type_zval , & prop_group_zval );
1066
1081
}
1067
- ast_update_property_long ( & prop_group_zval , AST_STR ( str_flags ), 0 , AST_CACHE_SLOT_FLAGS );
1082
+ AST_NODE_SET_PROP_FLAGS ( obj , 0 );
1068
1083
}
1069
1084
#endif
1070
1085
#if PHP_VERSION_ID < 80000
@@ -1073,7 +1088,7 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) {
1073
1088
zval attributes_zval ;
1074
1089
ZVAL_COPY_VALUE (& const_decl_zval , zv );
1075
1090
ZVAL_NULL (& attributes_zval );
1076
- ast_update_property_long ( zv , AST_STR ( str_flags ), 0 , AST_CACHE_SLOT_FLAGS );
1091
+ AST_NODE_SET_PROP_FLAGS ( obj , 0 );
1077
1092
// For version 80, create an AST_CLASS_CONST_GROUP wrapping the created AST_CLASS_CONST_DECL
1078
1093
ast_create_virtual_node_ex (
1079
1094
zv , ZEND_AST_CLASS_CONST_GROUP , ast -> attr , zend_ast_get_lineno (ast ), state , 2 , & const_decl_zval , & attributes_zval );
@@ -1255,21 +1270,21 @@ static inline const ast_flag_info *ast_get_flag_info(uint16_t ast_kind) {
1255
1270
1256
1271
static void ast_build_metadata (zval * result ) {
1257
1272
size_t i ;
1258
- array_init (result );
1273
+ array_init_size (result , ast_kinds_count );
1259
1274
for (i = 0 ; i < ast_kinds_count ; i ++ ) {
1260
1275
zend_ast_kind kind = ast_kinds [i ];
1261
1276
const ast_flag_info * flag_info = ast_get_flag_info (kind );
1262
1277
zval info_zv , tmp_zv ;
1278
+ zend_object * obj ;
1263
1279
1264
1280
object_init_ex (& info_zv , ast_metadata_ce );
1281
+ obj = Z_OBJ (info_zv );
1265
1282
1266
1283
/* kind */
1267
- ast_update_property_long ( & info_zv , AST_STR ( str_kind ), kind , NULL );
1284
+ ZVAL_LONG ( AST_METADATA_PROP_KIND ( obj ), kind );
1268
1285
1269
1286
/* name */
1270
- ZVAL_STRING (& tmp_zv , ast_kind_to_name (kind ));
1271
- Z_TRY_DELREF (tmp_zv );
1272
- ast_update_property (& info_zv , AST_STR (str_name ), & tmp_zv , NULL );
1287
+ ZVAL_STRING (AST_METADATA_PROP_NAME (obj ), ast_kind_to_name (kind ));
1273
1288
1274
1289
/* flags */
1275
1290
array_init (& tmp_zv );
@@ -1279,12 +1294,10 @@ static void ast_build_metadata(zval *result) {
1279
1294
add_next_index_string (& tmp_zv , * flag );
1280
1295
}
1281
1296
}
1282
- Z_TRY_DELREF (tmp_zv );
1283
- ast_update_property (& info_zv , AST_STR (str_flags ), & tmp_zv , NULL );
1297
+ ZVAL_ARR (AST_METADATA_PROP_FLAGS (obj ), Z_ARRVAL (tmp_zv ));
1284
1298
1285
1299
/* flagsCombinable */
1286
- ZVAL_BOOL (& tmp_zv , flag_info && flag_info -> combinable );
1287
- ast_update_property (& info_zv , AST_STR (str_flagsCombinable ), & tmp_zv , NULL );
1300
+ ZVAL_BOOL (AST_METADATA_PROP_FLAGS_COMBINABLE (obj ), flag_info && flag_info -> combinable );
1288
1301
1289
1302
add_index_zval (result , kind , & info_zv );
1290
1303
}
@@ -1340,27 +1353,27 @@ PHP_METHOD(ast_Node, __construct) {
1340
1353
Z_PARAM_LONG_EX (lineno , linenoNull , 1 , 0 )
1341
1354
ZEND_PARSE_PARAMETERS_END ();
1342
1355
1343
- zval * zv = getThis ( );
1356
+ zend_object * obj = Z_OBJ_P ( ZEND_THIS );
1344
1357
1345
1358
switch (num_args ) {
1346
1359
case 4 :
1347
1360
if (!linenoNull ) {
1348
- ast_update_property_long ( zv , AST_STR ( str_lineno ), lineno , AST_CACHE_SLOT_LINENO );
1361
+ AST_NODE_SET_PROP_LINENO ( obj , lineno );
1349
1362
}
1350
1363
/* Falls through - break missing intentionally */
1351
1364
case 3 :
1352
1365
if (children != NULL ) {
1353
- ast_update_property ( zv , AST_STR ( str_children ), children , AST_CACHE_SLOT_CHILDREN );
1366
+ ZVAL_COPY ( AST_NODE_PROP_CHILDREN ( obj ), children );
1354
1367
}
1355
1368
/* Falls through - break missing intentionally */
1356
1369
case 2 :
1357
1370
if (!flagsNull ) {
1358
- ast_update_property_long ( zv , AST_STR ( str_flags ), flags , AST_CACHE_SLOT_FLAGS );
1371
+ AST_NODE_SET_PROP_FLAGS ( obj , flags );
1359
1372
}
1360
1373
/* Falls through - break missing intentionally */
1361
1374
case 1 :
1362
1375
if (!kindNull ) {
1363
- ast_update_property_long ( zv , AST_STR ( str_kind ), kind , AST_CACHE_SLOT_KIND );
1376
+ AST_NODE_SET_PROP_KIND ( obj , kind );
1364
1377
}
1365
1378
/* Falls through - break missing intentionally */
1366
1379
case 0 :
@@ -1381,7 +1394,6 @@ PHP_MINFO_FUNCTION(ast) {
1381
1394
}
1382
1395
1383
1396
PHP_RINIT_FUNCTION (ast ) {
1384
- memset (AST_G (cache_slots ), 0 , sizeof (void * ) * AST_NUM_CACHE_SLOTS );
1385
1397
ZVAL_UNDEF (& AST_G (metadata ));
1386
1398
return SUCCESS ;
1387
1399
}
0 commit comments