diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 959f1683..a17adf3c 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -669,6 +669,12 @@ class CompilerBase extends \PhpAot\Core\Translator if ($this->isStdContainer($varName)) { return $varName . '_ref'; } + // $GLOBALS is an INDIRECT to &EG(symbol_table), + // whose refcount MUST NOT be directly manipulated. + // Use php_globals_array() to create a separated copy. + if ($varName === 'GLOBALS') { + return 'php_globals_array()'; + } return $varName; case 'Scalar_MagicConst_File': case 'Scalar_MagicConst_Dir': @@ -3155,6 +3161,9 @@ class CompilerBase extends \PhpAot\Core\Translator } } $expr = $this->parseIdentifier($arg->value); + if ($this->isVarExpr($arg->value) and $arg->value->name === 'GLOBALS') { + return 'php_globals_array()'; + } if ($this->isVarExpr($arg->value) and $this->isStdContainer($arg->value->name)) { return $this->convertArrayExpr($expr . '_ref'); } @@ -5664,6 +5673,10 @@ class CompilerBase extends \PhpAot\Core\Translator } $code .= $this->genLocalVarDecl($this->context->localVars); foreach ($this->context->globalVars as $name => $type) { + // $GLOBALS is handled via php_globals_array() at each read site + if ($name === 'GLOBALS') { + continue; + } $code .= $this->getIndent() . self::TYPE_VAR . ' &' . $name . ' = ' . $this->escapeGlobalVar($name) . ';' . PHP_EOL; } foreach ($this->context->objectProps as $name => $info) { diff --git a/src/Php/Optimizer/FuncCallOptimizer.php b/src/Php/Optimizer/FuncCallOptimizer.php index 2863d24d..f0b9a08d 100644 --- a/src/Php/Optimizer/FuncCallOptimizer.php +++ b/src/Php/Optimizer/FuncCallOptimizer.php @@ -336,7 +336,11 @@ trait FuncCallOptimizer protected function getArg(Node\Expr\FuncCall $expr, int $i): string { - return $this->parseIdentifier($expr->args[$i]->value); + $arg = $expr->args[$i]->value; + if ($this->isVarExpr($arg) and $arg->name === 'GLOBALS') { + return 'php_globals_array()'; + } + return $this->parseIdentifier($arg); } protected function getRefArg(Node\Expr\FuncCall $expr, int $i): string diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 3432cabc..38e01484 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -864,12 +864,9 @@ CODE; $code .= '// global vars ' . PHP_EOL; foreach ($this->globalVars as $name => $type) { if ($name == 'GLOBALS') { - $var = $this->escapeGlobalVar($name); - $code .= 'ZVAL_ARR(&globals_array, &EG(symbol_table));' . PHP_EOL; - $code .= 'ZVAL_INDIRECT(' . $var. '.ptr(), &globals_array);' . PHP_EOL; - } else { - $code .= 'php::initGlobal(' . $this->genCharPtr($name) . ', ' . $this->escapeGlobalVar($name) . ');' . PHP_EOL; + continue; } + $code .= 'php::initGlobal(' . $this->genCharPtr($name) . ', ' . $this->escapeGlobalVar($name) . ');' . PHP_EOL; } $code .= '// static property ' . PHP_EOL;