[GIT-PULLS] [php-src] PR #23305: Elide provably-passing return type checks at compile time
[email protected] (staabm)
| Newsgroups | php.git-pulls |
|---|---|
| Message-ID | <[email protected]> |
Pull Request: https://github.com/php/php-src/pull/23305 Author: staabm disclaimer: this change was generated by claude opus. I have little experience with php-src development ---- Without the opcache optimizer every 'return <expr>;' in a typed function executes ZEND_VERIFY_RETURN_TYPE. Skip emitting it when the check provably always passes: - expressions whose opcode always produces a specific type accepted by the return type: comparisons, instanceof, isset/empty and boolean operators produce bool; concatenation produces string; - 'return $this->prop;' where the property is declared in the class being compiled and its type is a subtype of the return type. Property types are invariant under inheritance, and typed property reads always yield conforming values: uninitialized reads throw before the return, and __get()/get-hook results are verified against the property type. Only same-class declarations are visible during method compilation, which keeps the proof local. Closures are excluded (Closure::bind can rebind scopes), as are by-ref returns, generators, union/intersection property types and context-dependent return types (static, callable). Coercion semantics are preserved by requiring the value type set to be a subset of the return type set (e.g. an int property returned as float still emits the check). Getter-style code drops one opcode per return; 'return $x === null;' style predicates drop the check entirely. ---- before PR ``` ➜ php-src git:(elide-return) ✗ ./sapi/cli/php_old -n -dopcache.enable_cli=0 return_type_check_elision_repro.php PHP 8.6.0-dev iterations=5000000 rounds=7 calls_per_round=40000000 case best(s) avg(s) sink -------------------------------------------------- getter-direct 0.358463 0.359450 280000000 getter-control 0.409889 0.412215 280000000 cmp-direct 0.462745 0.465084 39999990 cmp-control 0.529274 0.532243 39999990 Direct/control ratio inside each pair (best time, lower is better): getter 0.8745x cmp 0.8743x ``` after PR ``` ➜ php-src git:(elide-return) ✗ ./sapi/cli/php -n -dopcache.enable_cli=0 return_type_check_elision_repro.php PHP 8.6.0-dev iterations=5000000 rounds=7 calls_per_round=40000000 case best(s) avg(s) sink -------------------------------------------------- getter-direct 0.337137 0.337611 280000000 getter-control 0.415257 0.416750 280000000 cmp-direct 0.448156 0.451637 39999990 cmp-control 0.536600 0.539734 39999990 Direct/control ratio inside each pair (best time, lower is better): getter 0.8119x cmp 0.8352x ``` using [return_type_check_elision_repro.php](https://gist.github.com/staabm/127abcf5aafc47d0b178eda39e525ad2)