fix(compiler): keep method cache lifetime aligned with class

debug/ci-class-id-cache
韩天峰 11 hours ago
parent a6cc11c6d7
commit 0ac6dfe499
  1. 20
      phpunit/src/CompilerBaseApiTest.php
  2. 13
      src/CompilerBase.php

@ -78,6 +78,26 @@ class CompilerBaseApiTest extends TestCase
return $m->invoke($this->compiler, ...$args); return $m->invoke($this->compiler, ...$args);
} }
public function testMethodCacheKeepsPreviouslyAssignedClassLifetime(): void
{
// The two maps have independent ID spaces. This reproduces the tpc
// bootstrap ordering where both classes occupied slot zero.
$this->setPropertyValue('classMap', ['LateKnownClass' => 0]);
$this->setPropertyValue('classIndex', 1);
$this->setPropertyValue('persistentClassMap', ['StableResolver' => 0]);
$this->setPropertyValue('persistentClassIndex', 1);
$methodPtr = $this->invokeMethod('getMethodPtr', 'LateKnownClass', 'run');
$this->assertStringStartsWith('get_method(0, ', $methodPtr);
$this->assertStringContainsString(', 0, ', $methodPtr);
$this->assertSame(
['LateKnownClass::run' => 0],
$this->getPropertyValue('funcMap'),
);
$this->assertSame([], $this->getPropertyValue('persistentFuncMap'));
}
private function fixturePath(string $file): string private function fixturePath(string $file): string
{ {
return __DIR__ . '/../code/compiler_api/' . $file; return __DIR__ . '/../code/compiler_api/' . $file;

@ -1277,6 +1277,19 @@ class CompilerBase implements PropertyAccessContext
{ {
if (str_contains($funcName, '::')) { if (str_contains($funcName, '::')) {
[$class] = explode('::', $funcName, 2); [$class] = explode('::', $funcName, 2);
// Class and method caches use parallel lifetime domains. Once a
// class has been assigned an ID, keep every subsequently resolved
// method in the same domain even if the class becomes visible in
// the symbol repository later in the prepare pass. Otherwise a
// request-local class ID may be used to index persistentClassMap.
if (isset($this->classMap[$class])) {
return false;
}
if (isset($this->persistentClassMap[$class])) {
return true;
}
return $this->isProcessStableClass($class); return $this->isProcessStableClass($class);
} }
if ($this->hasFunction($funcName)) { if ($this->hasFunction($funcName)) {

Loading…
Cancel
Save