diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index d50af5f2..4f35f874 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -102,6 +102,8 @@ class CompilerBase extends \PhpAot\Core\Translator public const string OP_NOT_EMPTY = 'notEmpty'; public const string OP_REFVAL = 'toReference'; public const string OP_NOP = "if (0) {}\n"; + // 超过65536字节的数组,将从栈上转移到堆 + public const int MAX_BYTES_IN_STACK = 65536; protected string $lang = 'PHP'; protected string $cppCompiler = ''; protected array $literalStrings = []; @@ -5367,8 +5369,12 @@ class CompilerBase extends \PhpAot\Core\Translator $code .= $this->getIndent(); if ($type === self::TYPE_STD_ARRAY) { $info = $this->context->stdArrays[$name]; - $code .= "auto {$name}_unique_ptr = std::make_unique<{$info['decl']}>();\n"; - $code .= $this->getIndent() . ' auto &' . $name . ' = *' . $name . '_unique_ptr;'; + if ($info['bytes'] > self::MAX_BYTES_IN_STACK) { + $code .= "auto {$name}_unique_ptr = std::make_unique<{$info['decl']}>();\n"; + $code .= $this->getIndent() . ' auto &' . $name . ' = *' . $name . '_unique_ptr;'; + } else { + $code .= $info['decl'] . ' ' . $name . '{};'; + } } else { $code .= $type . ' ' . $name; if ($type === self::TYPE_INT or $type === self::TYPE_FLOAT or $type === self::TYPE_BOOL) { diff --git a/src/Php/Parser/StdArrayParser.php b/src/Php/Parser/StdArrayParser.php index a41988ae..6e532856 100644 --- a/src/Php/Parser/StdArrayParser.php +++ b/src/Php/Parser/StdArrayParser.php @@ -108,6 +108,7 @@ trait StdArrayParser { $tmp = $expr; $nesting = []; + $totalBytes = 0; while (true) { if (count($tmp->args) !== 2) { @@ -116,6 +117,7 @@ trait StdArrayParser if (!$this->isScalarInt($tmp->args[1]->value)) { $this->fatalError($tmp, 'std::array() expects second argument to be an integer'); } + $byte = 0; $size = $tmp->args[1]->value->value; $nesting[] = $size; $typeExpr = $tmp->args[0]->value; @@ -126,12 +128,15 @@ trait StdArrayParser switch ($typeExpr->name->name) { case 'type_int': $type = self::TYPE_INT; + $byte = 8; break; case 'type_float': $type = self::TYPE_FLOAT; + $byte = 8; break; case 'type_bool': $type = self::TYPE_BOOL; + $byte = 1; break; default: $this->fatalError($tmp, 'An incorrect `std::array` definition'); @@ -139,6 +144,7 @@ trait StdArrayParser } break; } + $totalBytes += $size * $byte; if ($this->isStaticCall($typeExpr)) { $tmp = $typeExpr; if (!$this->isNameExpr($tmp->class) || !$this->isIdExpr($tmp->name) || $tmp->class->toString() !== 'std' || $tmp->name->toString() !== 'array') { @@ -158,6 +164,7 @@ trait StdArrayParser 'decl' => $decl, 'type' => $type, 'sizes' => array_reverse($nesting), + 'bytes' => $totalBytes, ]; return '// ' . $decl; }