-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Fix GH-22857: JIT wrong code for FETCH_OBJ_FUNC_ARG with property hooks #22897
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
zhaohao19941221
wants to merge
8
commits into
php:master
Choose a base branch
from
zhaohao19941221:fix/gh-22857-jit-fetch-obj-func-arg-hook
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+150
−2
Open
Changes from 3 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
4add960
Fix GH-22857: JIT wrong code for FETCH_OBJ_FUNC_ARG with property hooks
1720279
Merge branch 'master' into fix/gh-22857-jit-fetch-obj-func-arg-hook
287ce80
Fix gh22857.phpt: avoid unrelated pre-existing JIT leak in the warm-u…
a447b39
Update ext/opcache/tests/jit/gh22857.phpt
zhaohao19941221 05c5cc3
Update ext/opcache/tests/jit/gh22857.phpt
zhaohao19941221 5c4816c
Merge branch 'master' into fix/gh-22857-jit-fetch-obj-func-arg-hook
10821a1
fix: Improve gh22857.phpt: use deterministic assertion for FETCH_OBJ_…
d753c5b
Merge branch 'master' into fix/gh-22857-jit-fetch-obj-func-arg-hook
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| --TEST-- | ||
| GH-22857: Function JIT emits wrong code for FETCH_OBJ_FUNC_ARG on a property hook (SIMPLE_GET fast path) | ||
| --INI-- | ||
| opcache.enable=1 | ||
| opcache.enable_cli=1 | ||
| opcache.jit_buffer_size=64M | ||
| opcache.jit=1205 | ||
| opcache.jit_hot_func=1 | ||
| --EXTENSIONS-- | ||
| opcache | ||
| --FILE-- | ||
| <?php | ||
| namespace Test; | ||
|
|
||
| interface HandlerInterface { public function noop(): void; } | ||
|
|
||
| final class DefaultHandler implements HandlerInterface { | ||
| private static ?self $i = null; | ||
| public static function getInstance(): self { return self::$i ??= new self(); } | ||
| public function noop(): void {} | ||
| } | ||
|
|
||
| /* Repro of the original issue: virtual property hook read via | ||
| * FETCH_OBJ_FUNC_ARG under function JIT, where the getter frame is pushed | ||
| * by the SIMPLE_GET fast path in the shared FETCH_OBJ_R handler but the | ||
| * JIT-compiled FUNC_ARG opcode has no hook-enter guard. */ | ||
| class Container { | ||
| public protected(set) HandlerInterface $handler; | ||
|
|
||
| public string $path { | ||
| get => self::build($this->kind, $this->id); | ||
| } | ||
|
|
||
| protected mixed $prev = null; | ||
|
|
||
| public function __construct( | ||
| public protected(set) string $kind, | ||
| public protected(set) string $id, | ||
| ) { | ||
| $this->handler = DefaultHandler::getInstance(); | ||
| } | ||
|
|
||
| public static function build(string $k, string $i): string { | ||
| return "/nonexistent/gh22857_{$k}_{$i}.dat"; | ||
| } | ||
|
|
||
| public function step(): void { | ||
| /* Unqualified namespaced-fallback call so op1 of SEND is a | ||
| * FETCH_OBJ_FUNC_ARG (INIT_NS_FCALL_BY_NAME). @ silences the | ||
| * expected file-not-found warning. */ | ||
| $r = @file_get_contents($this->path); | ||
| if ($r !== false) { | ||
| throw new \RuntimeException('unexpected non-false return'); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| $c = new Container('alpha', 'beta'); | ||
| for ($i = 0; $i < 200; $i++) { | ||
| $c->step(); | ||
| } | ||
|
|
||
| /* Sibling-slot variant: a preceding plain FETCH_OBJ_R can prime the | ||
| * SIMPLE_GET bit on the property cache slot; compact_literals shares the | ||
| * slot between FETCH_OBJ_R and FETCH_OBJ_FUNC_ARG for the same property, | ||
| * so a following FETCH_OBJ_FUNC_ARG will consume that bit and hit the | ||
| * SIMPLE_GET fast path. Without the hook-enter guard it reads garbage | ||
| * from an adjacent property slot. */ | ||
| class Container2 { | ||
| public protected(set) HandlerInterface $handler; | ||
|
|
||
| public string $path { | ||
| get => self::build($this->kind, $this->id); | ||
| } | ||
|
|
||
| protected mixed $prev = null; | ||
|
|
||
| public function __construct( | ||
| public protected(set) string $kind, | ||
| public protected(set) string $id, | ||
| ) { | ||
| $this->handler = DefaultHandler::getInstance(); | ||
| } | ||
|
|
||
| public static function build(string $k, string $i): string { | ||
| return "/nonexistent/gh22857b_{$k}_{$i}.dat"; | ||
| } | ||
|
|
||
| public function step(): void { | ||
| /* FETCH_OBJ_R primes SIMPLE_GET on the shared slot. The hook | ||
| * result is stored into a property (ownership transfer) instead | ||
| * of a local, so this test stays independent of how the JIT | ||
| * releases temporaries of hooked property reads. */ | ||
| $this->prev = $this->path; | ||
| $r = @file_get_contents($this->path); // FETCH_OBJ_FUNC_ARG consumes the primed bit | ||
| if ($r !== false || !\is_string($this->prev)) { | ||
| throw new \RuntimeException('unexpected values'); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| $c2 = new Container2('alpha', 'beta'); | ||
| for ($i = 0; $i < 200; $i++) { | ||
| $c2->step(); | ||
| } | ||
|
zhaohao19941221 marked this conversation as resolved.
Outdated
|
||
|
|
||
| echo "OK\n"; | ||
| ?> | ||
| --EXPECT-- | ||
| OK | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.