refactor(compiler): strongly type symbol cache IDs

debug/ci-class-id-cache
韩天峰 8 hours ago
parent 1b235d0769
commit 8f32497de7
  1. 11
      phpunit/src/CompilerBaseApiTest.php
  2. 21
      src/CompilerBase.php
  3. 67
      src/Translator.php

@ -89,8 +89,8 @@ class CompilerBaseApiTest extends TestCase
$methodPtr = $this->invokeMethod('getMethodPtr', 'LateKnownClass', 'run');
$this->assertStringStartsWith('get_method(0, ', $methodPtr);
$this->assertStringContainsString(', 0, ', $methodPtr);
$this->assertStringStartsWith('get_method(RequestFuncId{0}, ', $methodPtr);
$this->assertStringContainsString(', RequestClassId{0}, ', $methodPtr);
$this->assertSame(
['LateKnownClass::run' => 0],
$this->getPropertyValue('funcMap'),
@ -1258,8 +1258,13 @@ YAML);
'static php::PersistentCacheSlot<uint32_t> php_persistent_property_map',
$extension,
);
$this->assertStringContainsString('enum class RequestClassId : uint32_t {};', $data);
$this->assertStringContainsString('enum class PersistentClassId : uint32_t {};', $data);
$this->assertStringContainsString('enum class RequestFuncId : uint32_t {};', $data);
$this->assertStringContainsString('enum class PersistentFuncId : uint32_t {};', $data);
$this->assertStringContainsString('enum class PersistentPropertyId : uint32_t {};', $data);
$this->assertStringContainsString('get_persistent_class', $extension);
$this->assertStringContainsString('php::getPersistentCache(php_persistent_class_map[class_id]', $extension);
$this->assertStringContainsString('php::getPersistentCache(php_persistent_class_map[index]', $extension);
$this->assertStringContainsString('for (auto &slot : php_persistent_class_map)', $extension);
$this->assertStringContainsString('php::resetPersistentCache(slot);', $extension);
$this->assertStringNotContainsString('#ifdef ZTS', $data);

@ -1358,8 +1358,10 @@ class CompilerBase implements PropertyAccessContext
protected function getClassEntryPtr(string $className): string
{
$id = $this->getClassId($className);
$helper = isset($this->persistentClassMap[$className]) ? 'get_persistent_class' : 'get_class';
return $helper . '(' . $id . ', ' . $this->getLiteralString($className) . ')';
$persistent = isset($this->persistentClassMap[$className]);
$helper = $persistent ? 'get_persistent_class' : 'get_class';
$idType = $persistent ? 'PersistentClassId' : 'RequestClassId';
return $helper . '(' . $idType . '{' . $id . '}, ' . $this->getLiteralString($className) . ')';
}
/**
@ -1420,8 +1422,10 @@ class CompilerBase implements PropertyAccessContext
throw new \LogicException('Class methods must be resolved through getMethodPtr()');
}
$id = $this->getFuncId($funcName);
$helper = isset($this->persistentFuncMap[$funcName]) ? 'get_persistent_func' : 'get_func';
return $helper . '(' . $id . ', ' . $this->getLiteralString($funcName) . ')';
$persistent = isset($this->persistentFuncMap[$funcName]);
$helper = $persistent ? 'get_persistent_func' : 'get_func';
$idType = $persistent ? 'PersistentFuncId' : 'RequestFuncId';
return $helper . '(' . $idType . '{' . $id . '}, ' . $this->getLiteralString($funcName) . ')';
}
protected function getMethodPtr(string $class, string $method): string
@ -1442,14 +1446,17 @@ class CompilerBase implements PropertyAccessContext
));
}
$helper = $persistentMethod ? 'get_persistent_method' : 'get_method';
return $helper . '(' . $funcId . ', ' . $this->getLiteralString($method) . ', ' . $classId . ', ' . $this->getLiteralString($class) . ')';
$funcIdType = $persistentMethod ? 'PersistentFuncId' : 'RequestFuncId';
$classIdType = $persistentClass ? 'PersistentClassId' : 'RequestClassId';
return $helper . '(' . $funcIdType . '{' . $funcId . '}, ' . $this->getLiteralString($method)
. ', ' . $classIdType . '{' . $classId . '}, ' . $this->getLiteralString($class) . ')';
}
protected function getPropertyOffset(string $class, string $prop): string
{
$propId = $this->getPropertyId($class, $prop);
$classId = $this->getClassId($class);
return 'get_persistent_prop(' . $propId . ', ' . $this->getLiteralString($prop) . ', ' . $classId . ', ' . $this->getLiteralString($class) . ')';
return 'get_persistent_prop(PersistentPropertyId{' . $propId . '}, '
. $this->getLiteralString($prop) . ', ' . $this->getLiteralString($class) . ')';
}
protected function writeLog($msg): void

@ -777,13 +777,19 @@ class Translator extends Preprocessor
$lines[] = $pythonModuleDeclarations;
}
$lines[] = 'zend_class_entry *get_class(int class_id, const php::Str &class_name);';
$lines[] = 'zend_function *get_func(int func_id, const php::Str &func_name);';
$lines[] = 'zend_function *get_method(int func_id, const php::Str &method_name, int class_id, const php::Str &class_name);';
$lines[] = 'zend_class_entry *get_persistent_class(int class_id, const php::Str &class_name);';
$lines[] = 'zend_function *get_persistent_func(int func_id, const php::Str &func_name);';
$lines[] = 'zend_function *get_persistent_method(int func_id, const php::Str &method_name, int class_id, const php::Str &class_name);';
$lines[] = 'uint32_t get_persistent_prop(int prop_id, const php::Str &prop_name, int class_id, const php::Str &class_name);' . PHP_EOL;
$lines[] = 'enum class RequestClassId : uint32_t {};';
$lines[] = 'enum class PersistentClassId : uint32_t {};';
$lines[] = 'enum class RequestFuncId : uint32_t {};';
$lines[] = 'enum class PersistentFuncId : uint32_t {};';
$lines[] = 'enum class PersistentPropertyId : uint32_t {};' . PHP_EOL;
$lines[] = 'zend_class_entry *get_class(RequestClassId class_id, const php::Str &class_name);';
$lines[] = 'zend_function *get_func(RequestFuncId func_id, const php::Str &func_name);';
$lines[] = 'zend_function *get_method(RequestFuncId func_id, const php::Str &method_name, RequestClassId class_id, const php::Str &class_name);';
$lines[] = 'zend_class_entry *get_persistent_class(PersistentClassId class_id, const php::Str &class_name);';
$lines[] = 'zend_function *get_persistent_func(PersistentFuncId func_id, const php::Str &func_name);';
$lines[] = 'zend_function *get_persistent_method(PersistentFuncId func_id, const php::Str &method_name, PersistentClassId class_id, const php::Str &class_name);';
$lines[] = 'uint32_t get_persistent_prop(PersistentPropertyId prop_id, const php::Str &prop_name, const php::Str &class_name);' . PHP_EOL;
foreach ($this->getClassLikesWithConstants() as $classDef) {
foreach ($classDef->constants as $constant) {
@ -876,49 +882,56 @@ class Translator extends Preprocessor
$code .= "// functions \n";
$code .= <<<'CODE'
zend_class_entry *get_class(int class_id, const php::Str &class_name) {
if (UNEXPECTED(php_class_map[class_id] == nullptr)) {
php_class_map[class_id] = php::getClassEntrySafe(class_name);
zend_class_entry *get_class(RequestClassId class_id, const php::Str &class_name) {
const auto index = static_cast<uint32_t>(class_id);
if (UNEXPECTED(php_class_map[index] == nullptr)) {
php_class_map[index] = php::getClassEntrySafe(class_name);
}
return php_class_map[class_id];
return php_class_map[index];
}
zend_function *get_func(int func_id, const php::Str &func_name) {
if (UNEXPECTED(php_func_map[func_id] == nullptr)) {
php_func_map[func_id] = php::getFunction(func_name);
zend_function *get_func(RequestFuncId func_id, const php::Str &func_name) {
const auto index = static_cast<uint32_t>(func_id);
if (UNEXPECTED(php_func_map[index] == nullptr)) {
php_func_map[index] = php::getFunction(func_name);
}
return php_func_map[func_id];
return php_func_map[index];
}
zend_function *get_method(int func_id, const php::Str &method_name, int class_id, const php::Str &class_name) {
if (UNEXPECTED(php_func_map[func_id] == nullptr)) {
zend_function *get_method(RequestFuncId func_id, const php::Str &method_name, RequestClassId class_id, const php::Str &class_name) {
const auto index = static_cast<uint32_t>(func_id);
if (UNEXPECTED(php_func_map[index] == nullptr)) {
auto ce = get_class(class_id, class_name);
php_func_map[func_id] = php::getMethod(ce, method_name);
php_func_map[index] = php::getMethod(ce, method_name);
}
return php_func_map[func_id];
return php_func_map[index];
}
zend_class_entry *get_persistent_class(int class_id, const php::Str &class_name) {
return php::getPersistentCache(php_persistent_class_map[class_id], [&]() {
zend_class_entry *get_persistent_class(PersistentClassId class_id, const php::Str &class_name) {
const auto index = static_cast<uint32_t>(class_id);
return php::getPersistentCache(php_persistent_class_map[index], [&]() {
return php::getClassEntrySafe(class_name);
});
}
zend_function *get_persistent_func(int func_id, const php::Str &func_name) {
return php::getPersistentCache(php_persistent_func_map[func_id], [&]() {
zend_function *get_persistent_func(PersistentFuncId func_id, const php::Str &func_name) {
const auto index = static_cast<uint32_t>(func_id);
return php::getPersistentCache(php_persistent_func_map[index], [&]() {
return php::getFunction(func_name);
});
}
zend_function *get_persistent_method(int func_id, const php::Str &method_name, int class_id, const php::Str &class_name) {
return php::getPersistentCache(php_persistent_func_map[func_id], [&]() {
zend_function *get_persistent_method(PersistentFuncId func_id, const php::Str &method_name, PersistentClassId class_id, const php::Str &class_name) {
const auto index = static_cast<uint32_t>(func_id);
return php::getPersistentCache(php_persistent_func_map[index], [&]() {
auto ce = get_persistent_class(class_id, class_name);
return php::getMethod(ce, method_name);
});
}
uint32_t get_persistent_prop(int prop_id, const php::Str &prop_name, int class_id, const php::Str &class_name) {
auto value = php::getPersistentCache(php_persistent_property_map[prop_id], [&]() {
uint32_t get_persistent_prop(PersistentPropertyId prop_id, const php::Str &prop_name, const php::Str &class_name) {
const auto index = static_cast<uint32_t>(prop_id);
auto value = php::getPersistentCache(php_persistent_property_map[index], [&]() {
return php::getPropertyOffset(class_name, prop_name) + 1024;
});
return value - 1024;

Loading…
Cancel
Save