optimize(native): omit vptr from flat classes

master
韩天峰 3 weeks ago
parent 159df7dae0
commit 821c686ab0
  1. 24
      phpunit/src/NativeClass/NativeObjectStackPromotionCodegenTest.php
  2. 23
      src/NativeClass/NativeClassSupportTrait.php

@ -33,6 +33,30 @@ final class NativeObjectStackPromotionCodegenTest extends TestCase
'php::Int read();',
$header,
);
self::assertStringContainsString(
'~php_nativestackpromotionfixture() noexcept;',
$header,
);
self::assertStringNotContainsString(
'virtual ~php_nativestackpromotionfixture()',
$header,
);
self::assertStringContainsString(
'~php_nativestackfinalizerfixture() noexcept(false);',
$header,
);
self::assertStringNotContainsString(
'virtual ~php_nativestackfinalizerfixture()',
$header,
);
self::assertStringContainsString(
'virtual ~php_nativestackpromotionbase() noexcept;',
$header,
);
self::assertStringContainsString(
'virtual ~php_nativestackpromotionchild() noexcept override;',
$header,
);
self::assertStringContainsString(
'virtual php::Int __typephp_virtual_php_nativestackpromotionbase__readfrombase() override;',
$header,

@ -972,6 +972,17 @@ trait NativeClassSupportTrait
return false;
}
/** Whether this class declares or overrides a Native virtual method slot. */
protected function nativeObjectHasVirtualMethods(ClassDef $class): bool
{
foreach ([...$class->methods, ...$class->abstractMethodDefs] as $method) {
if ($this->getNativeVirtualMethodSlots($class, $method) !== []) {
return true;
}
}
return false;
}
protected function getNativeObjectArgumentType(ArgInfo $argument): ?string
{
$class = $argument->declaredClass ?: $argument->class;
@ -2010,6 +2021,8 @@ trait NativeClassSupportTrait
foreach ($classes as $class) {
$name = $this->getNativeObjectCppName($class);
$usesVirtualClone = $this->nativeObjectUsesVirtualClone($class);
$usesVtable = $usesVirtualClone || $this->nativeObjectHasVirtualMethods($class);
$hasNativeDestructor = $this->findNativeObjectMethod(
$class->getNamespacedName(false),
'__destruct',
@ -2026,9 +2039,13 @@ trait NativeClassSupportTrait
$code .= $this->getNativeMethodParameterDeclarations($constructor->functionDef);
}
$code .= ');' . PHP_EOL;
$code .= ' virtual ~' . $name . '() '
// The concrete type descriptor invokes the exact destructor, so
// destruction alone must not add a vptr to an otherwise flat class.
$code .= ' ' . ($usesVtable ? 'virtual ' : '') . '~' . $name . '() '
. ($hasNativeDestructor ? 'noexcept(false)' : 'noexcept')
. ($class->extends !== '' && $this->isNativeObjectClass($class->extends) ? ' override' : '')
. ($usesVtable
&& $class->extends !== ''
&& $this->isNativeObjectClass($class->extends) ? ' override' : '')
. ';' . PHP_EOL;
if ($class->hasMethod('__destruct')) {
$code .= ' void __typephp_finalize_destructor();' . PHP_EOL;
@ -2087,7 +2104,7 @@ trait NativeClassSupportTrait
}
}
}
if ($this->nativeObjectUsesVirtualClone($class)) {
if ($usesVirtualClone) {
$code .= ' virtual ' . $name . ' *' . self::NATIVE_VIRTUAL_CLONE_METHOD . '() const';
if ($class->extends !== '' && $this->isNativeObjectClass($class->extends)) {
$code .= ' override';

Loading…
Cancel
Save