字面量字符串优化,增加字面量表

pull/1/head
韩天峰 8 months ago
parent a25fe02e09
commit bf69a539a1
  1. 17
      examples/simple.php
  2. 1
      main.cc
  3. 42
      src/Php/Translator.php
  4. 30
      tests/aot/fib.phpt
  5. 25
      tests/aot/pi.phpt

@ -1,10 +1,13 @@
<?php
function main() {
$a = 0;
for ($i = 0; $i < 1000000; $i++)
$a++;
function Ack($m, $n){
if($m == 0) return $n+1;
if($n == 0) return Ack($m-1, 1);
return Ack($m - 1, Ack($m, ($n - 1)));
}
$thisisanotherlongname = 0;
for ($thisisalongname = 0; $thisisalongname < 1000000; $thisisalongname++)
$thisisanotherlongname++;
function main() {
$n = 7;
$r = Ack(3, $n);
print "Ack(3,$n): $r\n";
}

@ -29,6 +29,7 @@ int main(int cpp_argc, char **cpp_argv) {
#endif
argc.unset();
argv.unset();
php::request_shutdown();
php_embed_shutdown();
return rc;
}

@ -31,6 +31,8 @@ class Translator extends \PhpAot\Core\Translator
protected string $lang = 'PHP';
private string $cppCompiler = 'g++';
private array $arguments = [];
private array $literalStrings = [];
private int $literalStringIndex = 0;
private int $tmpVarIndex = 0;
private array $zendTypeMap = [
'int' => self::TYPE_INT,
@ -40,6 +42,7 @@ class Translator extends \PhpAot\Core\Translator
private array $headers = [
'phpx.h',
'phpx_helper.h',
'phpx_func.h',
'php_func_decl.h',
];
@ -229,6 +232,9 @@ class Translator extends \PhpAot\Core\Translator
foreach ($this->globalVars as $name => $type) {
$lines[] = 'extern ' . self::TYPE_VAR . ' ' . $name . ';';
}
$literalStringsCount = count($this->literalStrings);
$lines[] = 'extern php::Var _literal_strings[' . $literalStringsCount . '];' . PHP_EOL;
return implode(PHP_EOL, $lines) . PHP_EOL . PHP_EOL;
}
@ -286,6 +292,7 @@ class Translator extends \PhpAot\Core\Translator
return $this->doConvert($phpCode);
} catch (ReturnTypeChanged $e) {
// 某些情况,例如返回值变更,需要重新解析
$this->climate->cyan('Return type changed, retrying...');
continue;
}
}
@ -362,6 +369,13 @@ class Translator extends \PhpAot\Core\Translator
$this->internalFunctions[$name] = $this->functionDef;
}
foreach ($this->functionDef->argInfoList as $argInfo) {
$this->arguments[$argInfo->name] = $argInfo->type;
if (!$this->hasLocalVar($argInfo->name)) {
$this->addLocalVar($argInfo->name, $argInfo->type);
}
}
$this->indentLevel++;
$stmts = $this->parseStmts($v->stmts);
$this->indentLevel--;
@ -410,7 +424,8 @@ class Translator extends \PhpAot\Core\Translator
case 'Scalar_Float':
return $this->parseScalarFloat($expr);
case 'Scalar_String':
return '"' . $this->escapeString($expr->value) . '"';
$index = $this->literalStrings[$expr->value] ?? $this->addLiteralString($expr->value);
return '_literal_strings[' . $index . ']';
case 'Expr_ConstFetch':
return $this->parseConstFetch($expr);
default:
@ -426,9 +441,6 @@ class Translator extends \PhpAot\Core\Translator
$type = $this->parseType($param->type);
$name = $this->parseIdentifier($param->var);
$list[] = $type . ' ' . $name;
$this->arguments[$name] = $type;
$this->addLocalVar($name, $type);
$argInfo = new ArgInfo();
$argInfo->name = $name;
$argInfo->type = $type;
@ -806,6 +818,13 @@ class Translator extends \PhpAot\Core\Translator
$this->localVars[$name] = $type;
}
private function addLiteralString(string $value): int
{
$index = $this->literalStringIndex++;
$this->literalStrings[$value] = $index;
return $index;
}
private function addGlobalVar(string $name, string $type): void
{
$this->globalVars[$name] = $type;
@ -1162,8 +1181,8 @@ class Translator extends \PhpAot\Core\Translator
} else {
$fn = '"' . $name . '"';
}
if ($name === 'strlen' and $expr->args[0]->value->getType() === 'Expr_Variable') {
return '((php::Int)' . $this->parseIdentifier($expr->args[0]->value) . '.length())';
if ($name === 'strlen') {
return 'php::len(' . $this->parseIdentifier($expr->args[0]->value) . ')';
}
if (count($expr->args) == 1) {
switch ($name) {
@ -1894,6 +1913,17 @@ class Translator extends \PhpAot\Core\Translator
$lines[] = self::TYPE_VAR . ' ' . $name . ';';
}
$code .= implode(PHP_EOL, $lines) . PHP_EOL;
$code .= PHP_EOL;
$literalStringsCount = count($this->literalStrings);
$code .= 'php::Var _literal_strings[' . $literalStringsCount . '] = {' . PHP_EOL;
$this->indentLevel++;
foreach ($this->literalStrings as $str => $index) {
$code .= $this->getIndent() . 'php::String{ZEND_STRL("' . $this->escapeString($str) . '"), true},' . PHP_EOL;
}
$this->indentLevel--;
$code .= '};' . PHP_EOL;
file_put_contents($file, $code);
}

@ -0,0 +1,30 @@
--TEST--
Fibonacci
--FILE--
<?php
function fib(int $n): int
{
if ($n == 1 || $n == 2) {
return 1;
} else {
return fib($n - 1) + fib($n - 2);
}
}
function main()
{
$n = 40;
if ($n > 100) {
echo "Too big number\n";
exit(1);
} elseif ($n < 1) {
echo "Too small number\n";
exit(1);
}
$begin = microtime(true);
echo fib($n) . "\n";
}
?>
--EXPECT--
102334155

@ -0,0 +1,25 @@
--TEST--
π
--FILE--
<?php
function main()
{
ini_set("precision", 17);
$rounds = 1_0000_0000;
$stop = $rounds + 2;
$begin = microtime(true);
$x = 1.0;
$pi = 1.0;
for ($i = 2; $i <= $stop; $i++) {
$x = -1.0 + 2.0 * ($i & 0x1);
$pi += $x / (2 * $i - 1);
}
$pi *= 4.0;
print $pi . "\n";
}
?>
--EXPECT--
3.141592643589326
Loading…
Cancel
Save