@@ -132,6 +132,7 @@ PHPAPI zend_class_entry *reflection_property_hook_type_ptr;
132
132
typedef struct _property_reference {
133
133
zend_property_info * prop ;
134
134
zend_string * unmangled_name ;
135
+ void * cache_slot [3 ];
135
136
} property_reference ;
136
137
137
138
/* Struct for parameters */
@@ -1506,6 +1507,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_string *name,
1506
1507
reference = (property_reference * ) emalloc (sizeof (property_reference ));
1507
1508
reference -> prop = prop ;
1508
1509
reference -> unmangled_name = zend_string_copy (name );
1510
+ memset (reference -> cache_slot , 0 , sizeof (reference -> cache_slot ));
1509
1511
intern -> ptr = reference ;
1510
1512
intern -> ref_type = REF_TYPE_PROPERTY ;
1511
1513
intern -> ce = ce ;
@@ -5643,6 +5645,7 @@ ZEND_METHOD(ReflectionProperty, __construct)
5643
5645
reference = (property_reference * ) emalloc (sizeof (property_reference ));
5644
5646
reference -> prop = dynam_prop ? NULL : property_info ;
5645
5647
reference -> unmangled_name = zend_string_copy (name );
5648
+ memset (reference -> cache_slot , 0 , sizeof (reference -> cache_slot ));
5646
5649
intern -> ptr = reference ;
5647
5650
intern -> ref_type = REF_TYPE_PROPERTY ;
5648
5651
intern -> ce = ce ;
@@ -5794,9 +5797,10 @@ ZEND_METHOD(ReflectionProperty, getValue)
5794
5797
zval * object = NULL ;
5795
5798
zval * member_p = NULL ;
5796
5799
5797
- if (zend_parse_parameters (ZEND_NUM_ARGS (), "|o!" , & object ) == FAILURE ) {
5798
- RETURN_THROWS ();
5799
- }
5800
+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
5801
+ Z_PARAM_OPTIONAL
5802
+ Z_PARAM_OBJECT_EX (object , 1 , 0 )
5803
+ ZEND_PARSE_PARAMETERS_END ();
5800
5804
5801
5805
GET_REFLECTION_OBJECT_PTR (ref );
5802
5806
@@ -5813,13 +5817,29 @@ ZEND_METHOD(ReflectionProperty, getValue)
5813
5817
RETURN_THROWS ();
5814
5818
}
5815
5819
5816
- /* TODO: Should this always use intern->ce? */
5817
- if (!instanceof_function (Z_OBJCE_P (object ), ref -> prop ? ref -> prop -> ce : intern -> ce )) {
5818
- _DO_THROW ("Given object is not an instance of the class this property was declared in" );
5819
- RETURN_THROWS ();
5820
+ if (ref -> cache_slot [0 ] == Z_OBJCE_P (object )) {
5821
+ uintptr_t prop_offset = (uintptr_t ) ref -> cache_slot [1 ];
5822
+
5823
+ if (EXPECTED (IS_VALID_PROPERTY_OFFSET (prop_offset ))) {
5824
+ zval * retval = OBJ_PROP (Z_OBJ_P (object ), prop_offset );
5825
+ if (EXPECTED (Z_TYPE_INFO_P (retval ) != IS_UNDEF )) {
5826
+ RETURN_COPY_DEREF (retval );
5827
+ }
5828
+ }
5829
+ } else {
5830
+ /* TODO: Should this always use intern->ce? */
5831
+ if (!instanceof_function (Z_OBJCE_P (object ), ref -> prop ? ref -> prop -> ce : intern -> ce )) {
5832
+ _DO_THROW ("Given object is not an instance of the class this property was declared in" );
5833
+ RETURN_THROWS ();
5834
+ }
5820
5835
}
5821
5836
5822
- member_p = zend_read_property_ex (intern -> ce , Z_OBJ_P (object ), ref -> unmangled_name , 0 , & rv );
5837
+ zend_class_entry * old_scope = EG (fake_scope );
5838
+ EG (fake_scope ) = intern -> ce ;
5839
+ member_p = Z_OBJ_P (object )-> handlers -> read_property (Z_OBJ_P (object ),
5840
+ ref -> unmangled_name , BP_VAR_R , ref -> cache_slot , & rv );
5841
+ EG (fake_scope ) = old_scope ;
5842
+
5823
5843
if (member_p != & rv ) {
5824
5844
RETURN_COPY_DEREF (member_p );
5825
5845
} else {
@@ -5873,7 +5893,10 @@ ZEND_METHOD(ReflectionProperty, setValue)
5873
5893
Z_PARAM_ZVAL (value )
5874
5894
ZEND_PARSE_PARAMETERS_END ();
5875
5895
5876
- zend_update_property_ex (intern -> ce , object , ref -> unmangled_name , value );
5896
+ zend_class_entry * old_scope = EG (fake_scope );
5897
+ EG (fake_scope ) = intern -> ce ;
5898
+ object -> handlers -> write_property (object , ref -> unmangled_name , value , ref -> cache_slot );
5899
+ EG (fake_scope ) = old_scope ;
5877
5900
}
5878
5901
}
5879
5902
/* }}} */
@@ -5897,15 +5920,26 @@ ZEND_METHOD(ReflectionProperty, getRawValue)
5897
5920
property_reference * ref ;
5898
5921
zval * object ;
5899
5922
5900
- if ( zend_parse_parameters ( ZEND_NUM_ARGS (), "o" , & object ) == FAILURE ) {
5901
- RETURN_THROWS ();
5902
- }
5923
+ ZEND_PARSE_PARAMETERS_START ( 1 , 1 )
5924
+ Z_PARAM_OBJECT ( object )
5925
+ ZEND_PARSE_PARAMETERS_END ();
5903
5926
5904
5927
GET_REFLECTION_OBJECT_PTR (ref );
5905
5928
5906
- if (!instanceof_function (Z_OBJCE_P (object ), intern -> ce )) {
5907
- _DO_THROW ("Given object is not an instance of the class this property was declared in" );
5908
- RETURN_THROWS ();
5929
+ if (ref -> cache_slot [0 ] == Z_OBJCE_P (object )) {
5930
+ uintptr_t prop_offset = (uintptr_t ) ref -> cache_slot [1 ];
5931
+
5932
+ if (EXPECTED (IS_VALID_PROPERTY_OFFSET (prop_offset ))) {
5933
+ zval * retval = OBJ_PROP (Z_OBJ_P (object ), prop_offset );
5934
+ if (EXPECTED (Z_TYPE_INFO_P (retval ) != IS_UNDEF )) {
5935
+ RETURN_COPY_DEREF (retval );
5936
+ }
5937
+ }
5938
+ } else {
5939
+ if (!instanceof_function (Z_OBJCE_P (object ), intern -> ce )) {
5940
+ _DO_THROW ("Given object is not an instance of the class this property was declared in" );
5941
+ RETURN_THROWS ();
5942
+ }
5909
5943
}
5910
5944
5911
5945
zend_property_info * prop = reflection_property_get_effective_prop (ref ,
@@ -5918,7 +5952,12 @@ ZEND_METHOD(ReflectionProperty, getRawValue)
5918
5952
5919
5953
if (!prop || !prop -> hooks || !prop -> hooks [ZEND_PROPERTY_HOOK_GET ]) {
5920
5954
zval rv ;
5921
- zval * member_p = zend_read_property_ex (intern -> ce , Z_OBJ_P (object ), ref -> unmangled_name , 0 , & rv );
5955
+ zend_class_entry * old_scope = EG (fake_scope );
5956
+ EG (fake_scope ) = intern -> ce ;
5957
+ zval * member_p = Z_OBJ_P (object )-> handlers -> read_property (
5958
+ Z_OBJ_P (object ), ref -> unmangled_name , BP_VAR_R ,
5959
+ ref -> cache_slot , & rv );
5960
+ EG (fake_scope ) = old_scope ;
5922
5961
5923
5962
if (member_p != & rv ) {
5924
5963
RETURN_COPY_DEREF (member_p );
@@ -5935,11 +5974,14 @@ ZEND_METHOD(ReflectionProperty, getRawValue)
5935
5974
}
5936
5975
5937
5976
static void reflection_property_set_raw_value (zend_property_info * prop ,
5938
- zend_string * unmangled_name , reflection_object * intern ,
5977
+ zend_string * unmangled_name , void * cache_slot [ 3 ], reflection_object * intern ,
5939
5978
zend_object * object , zval * value )
5940
5979
{
5941
5980
if (!prop || !prop -> hooks || !prop -> hooks [ZEND_PROPERTY_HOOK_SET ]) {
5942
- zend_update_property_ex (intern -> ce , object , unmangled_name , value );
5981
+ zend_class_entry * old_scope = EG (fake_scope );
5982
+ EG (fake_scope ) = intern -> ce ;
5983
+ object -> handlers -> write_property (object , unmangled_name , value , cache_slot );
5984
+ EG (fake_scope ) = old_scope ;
5943
5985
} else {
5944
5986
zend_function * func = zend_get_property_hook_trampoline (prop , ZEND_PROPERTY_HOOK_SET , unmangled_name );
5945
5987
zend_call_known_instance_method_with_1_params (func , object , NULL , value );
@@ -5955,9 +5997,10 @@ ZEND_METHOD(ReflectionProperty, setRawValue)
5955
5997
5956
5998
GET_REFLECTION_OBJECT_PTR (ref );
5957
5999
5958
- if (zend_parse_parameters (ZEND_NUM_ARGS (), "oz" , & object , & value ) == FAILURE ) {
5959
- RETURN_THROWS ();
5960
- }
6000
+ ZEND_PARSE_PARAMETERS_START (2 , 2 ) {
6001
+ Z_PARAM_OBJECT (object )
6002
+ Z_PARAM_ZVAL (value )
6003
+ } ZEND_PARSE_PARAMETERS_END ();
5961
6004
5962
6005
zend_property_info * prop = reflection_property_get_effective_prop (ref ,
5963
6006
intern -> ce , Z_OBJ_P (object ));
@@ -5967,7 +6010,8 @@ ZEND_METHOD(ReflectionProperty, setRawValue)
5967
6010
RETURN_THROWS ();
5968
6011
}
5969
6012
5970
- reflection_property_set_raw_value (prop , ref -> unmangled_name , intern , Z_OBJ_P (object ), value );
6013
+ reflection_property_set_raw_value (prop , ref -> unmangled_name ,
6014
+ ref -> cache_slot , intern , Z_OBJ_P (object ), value );
5971
6015
}
5972
6016
5973
6017
static zend_result reflection_property_check_lazy_compatible (
@@ -6046,8 +6090,8 @@ ZEND_METHOD(ReflectionProperty, setRawValueWithoutLazyInitialization)
6046
6090
/* Do not trigger initialization */
6047
6091
Z_PROP_FLAG_P (var_ptr ) &= ~IS_PROP_LAZY ;
6048
6092
6049
- reflection_property_set_raw_value (prop , ref -> unmangled_name , intern , object ,
6050
- value );
6093
+ reflection_property_set_raw_value (prop , ref -> unmangled_name ,
6094
+ ref -> cache_slot , intern , object , value );
6051
6095
6052
6096
/* Mark property as lazy again if an exception prevented update */
6053
6097
if (EG (exception ) && prop_was_lazy && Z_TYPE_P (var_ptr ) == IS_UNDEF
@@ -6143,9 +6187,10 @@ ZEND_METHOD(ReflectionProperty, isInitialized)
6143
6187
zval * object = NULL ;
6144
6188
zval * member_p = NULL ;
6145
6189
6146
- if (zend_parse_parameters (ZEND_NUM_ARGS (), "|o!" , & object ) == FAILURE ) {
6147
- RETURN_THROWS ();
6148
- }
6190
+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
6191
+ Z_PARAM_OPTIONAL
6192
+ Z_PARAM_OBJECT_EX (object , 1 , 0 )
6193
+ ZEND_PARSE_PARAMETERS_END ();
6149
6194
6150
6195
GET_REFLECTION_OBJECT_PTR (ref );
6151
6196
@@ -6164,15 +6209,25 @@ ZEND_METHOD(ReflectionProperty, isInitialized)
6164
6209
RETURN_THROWS ();
6165
6210
}
6166
6211
6167
- /* TODO: Should this always use intern->ce? */
6168
- if (!instanceof_function (Z_OBJCE_P (object ), ref -> prop ? ref -> prop -> ce : intern -> ce )) {
6169
- _DO_THROW ("Given object is not an instance of the class this property was declared in" );
6170
- RETURN_THROWS ();
6212
+ if (ref -> cache_slot [0 ] == Z_OBJCE_P (object )) {
6213
+ uintptr_t prop_offset = (uintptr_t ) ref -> cache_slot [1 ];
6214
+
6215
+ if (EXPECTED (IS_VALID_PROPERTY_OFFSET (prop_offset ))) {
6216
+ zval * value = OBJ_PROP (Z_OBJ_P (object ), prop_offset );
6217
+ RETURN_BOOL (Z_TYPE_INFO_P (value ) != IS_UNDEF );
6218
+ }
6219
+ } else {
6220
+ /* TODO: Should this always use intern->ce? */
6221
+ if (!instanceof_function (Z_OBJCE_P (object ), ref -> prop ? ref -> prop -> ce : intern -> ce )) {
6222
+ _DO_THROW ("Given object is not an instance of the class this property was declared in" );
6223
+ RETURN_THROWS ();
6224
+ }
6171
6225
}
6172
6226
6173
6227
old_scope = EG (fake_scope );
6174
6228
EG (fake_scope ) = intern -> ce ;
6175
- retval = Z_OBJ_HT_P (object )-> has_property (Z_OBJ_P (object ), ref -> unmangled_name , ZEND_PROPERTY_EXISTS , NULL );
6229
+ retval = Z_OBJ_HT_P (object )-> has_property (Z_OBJ_P (object ),
6230
+ ref -> unmangled_name , ZEND_PROPERTY_EXISTS , ref -> cache_slot );
6176
6231
EG (fake_scope ) = old_scope ;
6177
6232
6178
6233
RETVAL_BOOL (retval );
0 commit comments