[php-src] PR #24198: Zend: Build the message of a persistent #[\Deprecated] once

From: Date: Thu, 08 Oct 2026 15:18:14 +0000
Subject: [php-src] PR #24198: Zend: Build the message of a persistent #[\Deprecated] once
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-39256@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/24198 Author: ArtUkrainskiy First of the two steps in GH-24191. Emitting the deprecation of an internal function constructs a \Deprecated object on every call to read its message and since: zend_get_attribute_object(), the constructor through zend_call_function() with named arguments, two property writes, two reads, destruction — about 2,900 of the 5,000 instructions a deprecated call costs, paid whether or not E_DEPRECATED is reported. The arguments of a persistent attribute are stub literals, so the suffix they produce never changes. This builds it on the first use and keeps it in the attribute as an immutable persistent string. The attribute is shared by every copy of the function (closures, reflection) and by every thread, so the store is a compare-and-swap and the string is freed with the attribute in attr_free(); readers take an acquire load. #[\NoDiscard] gets the same treatment. Attributes of user code keep building the object: their arguments may be constant expressions and their structs live in opcache's shared memory. ReflectionProperty::setAccessible(): 5,010 → 1,807 instructions per call, reported or filtered alike; the message is byte for byte the same (test added, covers repeated calls, a closure, reflection and an error handler). Checked on a debug ZTS build with --enable-werror: Zend/tests, ext/reflection, ext/date, ext/opcache (including with opcache.file_cache) pass. Measurements and how the cache behaves per SAPI: https://github.com/ArtUkrainskiy/php-src-bench/tree/main/reports/deprecation-cost

« previous php.git-pulls (#39256) next »