feat(debug): 添加调试信息支持以改进异常回溯功能

- 实现函数级别的调试信息生成,包括类方法和全局函数
- 添加命名空间前缀到调试函数名称中
- 集成 php::pushDebugFrame 和 php::popDebugFrame 用于运行时调试栈管理
- 添加调试信息启用和禁用机制
- 为嵌套函数调用添加异常传播测试用例
- 创建调试跟踪示例文件以验证功能实现
pull/1/head
韩天峰 3 months ago
parent 7ee2a161b9
commit 28b6c6e726
  1. 25
      examples/debug_trace.php
  2. 17
      src/Php/CompilerBase.php
  3. 22
      tests/aot/debug_exception.phpt

@ -0,0 +1,25 @@
<?php
function main()
{
foo();
}
function foo()
{
bar();
}
class Obj
{
function run()
{
$a = any(199);
var_dump($a[9]);
}
}
function bar()
{
$o = new Obj();
$o->run();
}

@ -1095,7 +1095,16 @@ class CompilerBase extends \PhpAot\Core\Translator
$code .= $this->genPropertyPromotion($argInfo);
}
$this->indentLevel--;
$code .= $this->genDebugInfo();
// 构建 PHP 级别的函数名用于 debug backtrace
if ($this->class) {
$debugName = $this->class . '::' . $this->function;
} else {
$debugName = $this->function;
if ($this->namespace) {
$debugName = $this->namespace . '\\' . $debugName;
}
}
$code .= $this->genDebugInfo(null, $debugName, $v->getStartLine());
// 函数中存在动态调用的函数,需要在运行时动态切换作用域
if ($this->methodDef and $this->methodDef->hasDynamicCall) {
@ -5541,12 +5550,16 @@ class CompilerBase extends \PhpAot\Core\Translator
return 'this_.call(' . $this->getMethodPtr($parentClass, $method) . ', ' . $this->parseCallArgs($expr->args) . ')';
}
protected function genDebugInfo(?NodeAbstract $stmt = null): string
protected function genDebugInfo(?NodeAbstract $stmt = null, string $functionName = '', int $startLine = 0): string
{
$code = '';
if ($this->debug) {
if ($stmt) {
$code .= 'php::traceDebugInfo("' . $this->escapeString($this->file) . '", ' . $stmt->getLine() . ');' . PHP_EOL;
} elseif ($functionName) {
$code .= 'php::enableDebugInfo();' . PHP_EOL;
$code .= 'php::pushDebugFrame("' . $this->escapeString($this->file) . '", ' . $startLine . ', "' . $this->escapeString($functionName) . '");' . PHP_EOL;
$code .= 'ON_SCOPE_EXIT(php::popDebugFrame());' . PHP_EOL;
} else {
$code .= 'php::enableDebugInfo();' . PHP_EOL;
}

@ -0,0 +1,22 @@
--TEST--
debug exception propagation through nested function calls
--FILE--
<?php
function inner() {
throw new Exception("error at inner level");
}
function middle() {
inner();
}
function main() {
try {
middle();
} catch (Exception $e) {
echo "Caught: " . $e->getMessage() . "\n";
echo "Exception class: " . get_class($e) . "\n";
}
}
?>
--EXPECT--
Caught: error at inner level
Exception class: Exception
Loading…
Cancel
Save