java - 递归程序执行期间出现 Truffle 语言运行时错误

标签 java jvm dsl truffle graalvm

我目前正在编写自己的 simplelanguage 实现 ( https://github.com/graalvm/simplelanguage/ ),以便学习如何使用 Truffle。

我编写了一些程序来测试我的实现,例如斐波那契算法的以下实现。

function fib(num) { 
  if (num <= 1) {return 1;}
  else {return fib(num-1) + fib(num-2); }
}

function fib(num) {
  if (num < 1) {return 0;}
  n1 = 0;
  n2 = 1;
  i = 1;
  while (i < num) {
    next = n2 + n1;
    n1 = n2;
    n2 = next;
    i = i + 1;
  }
  return n2;
}

虽然非递归版本可以使用任何大参数值(例如 10000)执行,但递归版本很快会引发运行时错误。

例如,我开发了一个简单的测试,它使用增量值执行递归 fib 函数,并获得以下结果:

fib(1) = 1(61)
fib(2) = 2(14)
fib(3) = 3(1)
fib(4) = 5(2)
fib(5) = 8(5)
fib(6) = 13(13)
fib(7) = 21(28)
fib(8) = 34(24)
fib(9) = 55(40)
fib(10) = 89(30)
fib(11) = 144(25)
fib(12) = 233(93)
fib(13) = 377(127)
fib(14) = 610(86)
fib(15) = 987(118)
fib(16) = 1597(248)
fib(17) = 2584(314)
fib(18) = 4181(402)
fib(19) = 6765(524)
fib(20) = 10946(372)
fib(21) = 17711(646)
[truffle] opt fail         Root@62804e23                                               |Reason org.graalvm.compiler.code.SourceStackTraceBailoutException$1: Object of type Lorg/graalvm/compiler/truffle/runtime/FrameWithoutBoxing; should not be materialized (must not let virtual object escape at node 10349|EndNode): 
org.graalvm.compiler.code.SourceStackTraceBailoutException$1: Object of type Lorg/graalvm/compiler/truffle/runtime/FrameWithoutBoxing; should not be materialized (must not let virtual object escape at node 10349|EndNode):
    at fr.mleduc.simplelanguage.revisitor.revisitors.ExecSLRevisitor$6.eval(ExecSLRevisitor.java:527)
    at fr.mleduc.simplelanguage.revisitor.model.objects.Root.execute(Root.java:34)
    at org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callProxy(OptimizedCallTarget.java:262)
    at org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callRoot(OptimizedCallTarget.java:251)
Caused by: org.graalvm.compiler.graph.VerificationError: Object of type Lorg/graalvm/compiler/truffle/runtime/FrameWithoutBoxing; should not be materialized (must not let virtual object escape at node 10349|EndNode):
    at org.graalvm.compiler.nodes.virtual.EnsureVirtualizedNode.ensureVirtualFailure(EnsureVirtualizedNode.java:98)
    at org.graalvm.compiler.nodes.virtual.CommitAllocationNode.lower(CommitAllocationNode.java:117)
    at org.graalvm.compiler.phases.common.LoweringPhase$Round.process(LoweringPhase.java:464)
    at org.graalvm.compiler.phases.common.LoweringPhase$Round.access$200(LoweringPhase.java:340)
    at org.graalvm.compiler.phases.common.LoweringPhase$Round$ProcessFrame.preprocess(LoweringPhase.java:404)
    at org.graalvm.compiler.phases.common.LoweringPhase.processBlock(LoweringPhase.java:563)
    at org.graalvm.compiler.phases.common.LoweringPhase$Round.run(LoweringPhase.java:389)
    at org.graalvm.compiler.phases.Phase.run(Phase.java:49)
    at org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:197)
    at org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:139)
    at org.graalvm.compiler.phases.PhaseSuite.run(PhaseSuite.java:212)
    at org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase.run(IncrementalCanonicalizerPhase.java:56)
    at org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase.run(IncrementalCanonicalizerPhase.java:38)
    at org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:197)
    at org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:139)
    at org.graalvm.compiler.phases.common.LoweringPhase.lower(LoweringPhase.java:260)
    at org.graalvm.compiler.phases.common.LoweringPhase.run(LoweringPhase.java:253)
    at org.graalvm.compiler.phases.common.LoweringPhase.run(LoweringPhase.java:92)
    at org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:197)
    at org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:139)
    at org.graalvm.compiler.phases.PhaseSuite.run(PhaseSuite.java:212)
    at org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:197)
    at org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:139)
    at org.graalvm.compiler.core.GraalCompiler.emitFrontEnd(GraalCompiler.java:256)
    at org.graalvm.compiler.core.GraalCompiler.compile(GraalCompiler.java:180)
    at org.graalvm.compiler.core.GraalCompiler.compileGraph(GraalCompiler.java:165)
    at org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl.compilePEGraph(TruffleCompilerImpl.java:447)
    at org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl.compileAST(TruffleCompilerImpl.java:393)
    at org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl$TruffleCompilationWrapper.performCompilation(TruffleCompilerImpl.java:546)
    at org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl$TruffleCompilationWrapper.performCompilation(TruffleCompilerImpl.java:495)
    at org.graalvm.compiler.core.CompilationWrapper.run(CompilationWrapper.java:169)
    at org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl.doCompile(TruffleCompilerImpl.java:224)
    at org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime.doCompile(GraalTruffleRuntime.java:710)
    at org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime$1.run(GraalTruffleRuntime.java:776)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
    at org.graalvm.compiler.core.CompilerThread.run(CompilerThread.java:42)

fib(22) = 28657(570)
fib(23) = 46368(735)
fib(24) = 75025(1235)

我试图将我自己的实现与官方 simplelanguage 实现进行比较,但没有找到确定问题根源的方法。

所以我的问题是,如何找到问题的根本原因?

PS:到目前为止,我没有足够的信息来识别此问题中包含的相关片段,但如果需要,请随时询问更多详细信息。谢谢:)

最佳答案

此处的错误是您让 VirtualFrame 对象脱离了部分计算的范围。堆栈跟踪的第一部分实际上是解释器在部分评估下的堆栈跟踪。特别是:

at fr.mleduc.simplelanguage.revisitor.revisitors.ExecSLRevisitor$6.eval(ExecSLRevisitor.java:527)
at fr.mleduc.simplelanguage.revisitor.model.objects.Root.execute(Root.java:34)

ExecSLRevisitor.java:527 周围的某些东西正在让 VirtualFrame 逃逸,但在不查看代码的情况下很难分辨出什么。

有两种解决方案:

  • 不要让框架逃脱
  • 此时具体化框架(请参阅VirtualFrame的javadoc)

关于java - 递归程序执行期间出现 Truffle 语言运行时错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51515512/

相关文章:

java - 我看不到框架内的组件

java - 膨胀 TableLayout 时出错

java - 改变 nimbus JPopupmenu 行为

java - JVM 进程如何分配内存?

php - 组合搜索对象并使用 $search->getQueries() 时出现意外的 BoolQuery

java - 如果 JUnit 测试在没有 @RunWith 注释的情况下也能按预期工作,为什么还要向我的 JUnit 测试添加 @RunWith 注释呢?

java - 将 Quarkus 应用于非 Maven、非 Gradle Java 项目

java - 维护线程池任务队列的类型信息

ruby - 调用具有多个参数和 block 的方法的 ruby​​ 语法是什么?

dsl - 成功的领域特定语言?你用哪一种?