@@ -254,44 +254,59 @@ ZEND_API void zend_clear_exception(void) /* {{{ */
254
254
}
255
255
/* }}} */
256
256
257
- /* Same as OBJ_PROP_NUM(), but checks the offset is correct when Zend is built in debug mode. */
258
- static zend_always_inline zval * zend_obj_prop_num_checked (zend_object * object , uint32_t prop_num , zend_string * str )
257
+ /* Same as writing to OBJ_PROP_NUM() when there are no hooks,
258
+ * but checks the offset is correct when Zend is built in debug mode.
259
+ * This is faster than going through the regular property write routine when the offset is known at compile time. */
260
+ static void zend_update_property_num_checked (zend_object * object , uint32_t prop_num , zend_string * member , zval * value )
259
261
{
262
+ if (UNEXPECTED (object -> ce -> num_hooked_props > 0 )) {
263
+ /* Property may have been overridden with a hook. */
264
+ zend_update_property_ex (object -> ce , object , member , value );
265
+ zval_ptr_dtor (value );
266
+ return ;
267
+ }
260
268
#if ZEND_DEBUG
261
269
zend_class_entry * old_scope = EG (fake_scope );
262
270
EG (fake_scope ) = i_get_exception_base (object );
263
- const zend_property_info * prop_info = zend_get_property_info (object -> ce , str , true);
271
+ const zend_property_info * prop_info = zend_get_property_info (object -> ce , member , true);
264
272
ZEND_ASSERT (OBJ_PROP_TO_NUM (prop_info -> offset ) == prop_num );
265
273
EG (fake_scope ) = old_scope ;
266
- #else
267
- ZEND_IGNORE_VALUE (str );
268
274
#endif
269
- return OBJ_PROP_NUM (object , prop_num );
275
+ zval * zv = OBJ_PROP_NUM (object , prop_num );
276
+ zval_ptr_safe_dtor (zv );
277
+ ZVAL_COPY_VALUE (zv , value );
270
278
}
271
279
272
280
static zend_object * zend_default_exception_new (zend_class_entry * class_type ) /* {{{ */
273
281
{
282
+ zval tmp ;
283
+ zval trace ;
274
284
zend_string * filename ;
275
285
276
286
zend_object * object = zend_objects_new (class_type );
277
287
object_properties_init (object , class_type );
278
- zval * trace = zend_obj_prop_num_checked (object , 5 , ZSTR_KNOWN (ZEND_STR_TRACE ));
279
288
280
289
if (EG (current_execute_data )) {
281
- zend_fetch_debug_backtrace (trace ,
290
+ zend_fetch_debug_backtrace (& trace ,
282
291
0 ,
283
292
EG (exception_ignore_args ) ? DEBUG_BACKTRACE_IGNORE_ARGS : 0 , 0 );
284
293
} else {
285
- ZVAL_EMPTY_ARRAY (trace );
294
+ ZVAL_EMPTY_ARRAY (& trace );
286
295
}
287
296
297
+ zend_update_property_num_checked (object , 5 , ZSTR_KNOWN (ZEND_STR_TRACE ), & trace );
298
+
288
299
if (EXPECTED ((class_type != zend_ce_parse_error && class_type != zend_ce_compile_error )
289
300
|| !(filename = zend_get_compiled_filename ()))) {
290
- ZVAL_STRING (zend_obj_prop_num_checked (object , 3 , ZSTR_KNOWN (ZEND_STR_FILE )), zend_get_executed_filename ());
291
- ZVAL_LONG (zend_obj_prop_num_checked (object , 4 , ZSTR_KNOWN (ZEND_STR_LINE )), zend_get_executed_lineno ());
301
+ ZVAL_STRING (& tmp , zend_get_executed_filename ());
302
+ zend_update_property_num_checked (object , 3 , ZSTR_KNOWN (ZEND_STR_FILE ), & tmp );
303
+ ZVAL_LONG (& tmp , zend_get_executed_lineno ());
304
+ zend_update_property_num_checked (object , 4 , ZSTR_KNOWN (ZEND_STR_LINE ), & tmp );
292
305
} else {
293
- ZVAL_STR_COPY (zend_obj_prop_num_checked (object , 3 , ZSTR_KNOWN (ZEND_STR_FILE )), filename );
294
- ZVAL_LONG (zend_obj_prop_num_checked (object , 4 , ZSTR_KNOWN (ZEND_STR_LINE )), zend_get_compiled_lineno ());
306
+ ZVAL_STR_COPY (& tmp , filename );
307
+ zend_update_property_num_checked (object , 3 , ZSTR_KNOWN (ZEND_STR_FILE ), & tmp );
308
+ ZVAL_LONG (& tmp , zend_get_compiled_lineno ());
309
+ zend_update_property_num_checked (object , 4 , ZSTR_KNOWN (ZEND_STR_LINE ), & tmp );
295
310
}
296
311
297
312
return object ;
@@ -311,7 +326,7 @@ ZEND_METHOD(Exception, __construct)
311
326
{
312
327
zend_string * message = NULL ;
313
328
zend_long code = 0 ;
314
- zval * object , * previous = NULL ;
329
+ zval tmp , * object , * previous = NULL ;
315
330
316
331
object = ZEND_THIS ;
317
332
@@ -320,21 +335,18 @@ ZEND_METHOD(Exception, __construct)
320
335
}
321
336
322
337
if (message ) {
323
- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 0 , ZSTR_KNOWN (ZEND_STR_MESSAGE ));
324
- zval_ptr_safe_dtor (tmp );
325
- ZVAL_STR_COPY (tmp , message );
338
+ ZVAL_STR_COPY (& tmp , message );
339
+ zend_update_property_num_checked (Z_OBJ_P (object ), 0 , ZSTR_KNOWN (ZEND_STR_MESSAGE ), & tmp );
326
340
}
327
341
328
342
if (code ) {
329
- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 2 , ZSTR_KNOWN (ZEND_STR_CODE ));
330
- zval_ptr_dtor (tmp );
331
- ZVAL_LONG (tmp , code );
343
+ ZVAL_LONG (& tmp , code );
344
+ zend_update_property_num_checked (Z_OBJ_P (object ), 2 , ZSTR_KNOWN (ZEND_STR_CODE ), & tmp );
332
345
}
333
346
334
347
if (previous ) {
335
- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 6 , ZSTR_KNOWN (ZEND_STR_PREVIOUS ));
336
- zval_ptr_safe_dtor (tmp );
337
- ZVAL_COPY (tmp , previous );
348
+ Z_ADDREF_P (previous );
349
+ zend_update_property_num_checked (Z_OBJ_P (object ), 6 , ZSTR_KNOWN (ZEND_STR_PREVIOUS ), previous );
338
350
}
339
351
}
340
352
/* }}} */
@@ -364,7 +376,7 @@ ZEND_METHOD(ErrorException, __construct)
364
376
zend_string * message = NULL , * filename = NULL ;
365
377
zend_long code = 0 , severity = E_ERROR , lineno ;
366
378
bool lineno_is_null = 1 ;
367
- zval * object , * previous = NULL ;
379
+ zval tmp , * object , * previous = NULL ;
368
380
369
381
if (zend_parse_parameters (ZEND_NUM_ARGS (), "|SllS!l!O!" , & message , & code , & severity , & filename , & lineno , & lineno_is_null , & previous , zend_ce_throwable ) == FAILURE ) {
370
382
RETURN_THROWS ();
@@ -373,41 +385,34 @@ ZEND_METHOD(ErrorException, __construct)
373
385
object = ZEND_THIS ;
374
386
375
387
if (message ) {
376
- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 0 , ZSTR_KNOWN (ZEND_STR_MESSAGE ));
377
- zval_ptr_safe_dtor (tmp );
378
- ZVAL_STR_COPY (tmp , message );
388
+ ZVAL_STR_COPY (& tmp , message );
389
+ zend_update_property_num_checked (Z_OBJ_P (object ), 0 , ZSTR_KNOWN (ZEND_STR_MESSAGE ), & tmp );
379
390
}
380
391
381
392
if (code ) {
382
- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 2 , ZSTR_KNOWN (ZEND_STR_CODE ));
383
- zval_ptr_dtor (tmp );
384
- ZVAL_LONG (tmp , code );
393
+ ZVAL_LONG (& tmp , code );
394
+ zend_update_property_num_checked (Z_OBJ_P (object ), 2 , ZSTR_KNOWN (ZEND_STR_CODE ), & tmp );
385
395
}
386
396
387
397
if (previous ) {
388
- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 6 , ZSTR_KNOWN (ZEND_STR_PREVIOUS ));
389
- zval_ptr_safe_dtor (tmp );
390
- ZVAL_COPY (tmp , previous );
398
+ Z_ADDREF_P (previous );
399
+ zend_update_property_num_checked (Z_OBJ_P (object ), 6 , ZSTR_KNOWN (ZEND_STR_PREVIOUS ), previous );
391
400
}
392
401
393
- {
394
- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 7 , ZSTR_KNOWN (ZEND_STR_SEVERITY ));
395
- zval_ptr_dtor (tmp );
396
- ZVAL_LONG (tmp , severity );
397
- }
402
+ ZVAL_LONG (& tmp , severity );
403
+ zend_update_property_num_checked (Z_OBJ_P (object ), 7 , ZSTR_KNOWN (ZEND_STR_SEVERITY ), & tmp );
398
404
399
405
if (filename ) {
400
- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 3 , ZSTR_KNOWN (ZEND_STR_FILE ));
401
- zval_ptr_dtor (tmp );
402
- ZVAL_STR_COPY (tmp , filename );
406
+ ZVAL_STR_COPY (& tmp , filename );
407
+ zend_update_property_num_checked (Z_OBJ_P (object ), 3 , ZSTR_KNOWN (ZEND_STR_FILE ), & tmp );
403
408
}
404
409
405
- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 4 , ZSTR_KNOWN (ZEND_STR_LINE ));
406
- zval_ptr_dtor (tmp );
407
410
if (!lineno_is_null ) {
408
- ZVAL_LONG (tmp , lineno );
411
+ ZVAL_LONG (& tmp , lineno );
412
+ zend_update_property_num_checked (Z_OBJ_P (object ), 4 , ZSTR_KNOWN (ZEND_STR_LINE ), & tmp );
409
413
} else if (filename ) {
410
- ZVAL_LONG (tmp , 0 );
414
+ ZVAL_LONG (& tmp , 0 );
415
+ zend_update_property_num_checked (Z_OBJ_P (object ), 4 , ZSTR_KNOWN (ZEND_STR_LINE ), & tmp );
411
416
}
412
417
}
413
418
/* }}} */
0 commit comments