docs/runtime-guide.md
withDebug
utility. Familiarize yourself with the different otpions. It is a useful
helper for running your programs and microbenchmarks with different Truffle
debugging options.final and @CompilationFinal. This is the
most important way Graal does constant-folding. Whenever a loop bound can be
compilation final, take advantage (and use @ExplodeLoop).@Specialization and read the generated
code. Without this understanding, it's way too easy to introduce very subtle
bugs to the language semantics.InteropLibrary) and embedder side (see Value). You want to make sure you
use the proper APIs in the proper places in the codebase. As a rule of thumb:
all code in the runtime project is language/instrumentation-side. All code
elsewhere is embedder-side. In particular, the only Graal dependency in
embedder code should be graal-sdk. If you find yourself pulling things like
truffle-api, you've done something wrong. Similarly, if you ever import
anything from org.graalvm.polyglot in the language code, you're doing
something wrong.JAVA_TOOL_OPTIONS="-Dpolygot.engine.TracePerformanceWarnings=all -Dpolyglot.engine.TraceTransferToInterpreter=true -Dpolyglot.engine.TraceDeoptimizeFrame=true -Dpolyglot.engine.TraceCompilation=true -Dpolyglot.engine.TraceCompilationDetails=true"
--log-level TRACE.JAVA_TOOL_OPTIONS="-Dpolyglot.engine.TraceInlining=true -Dpolyglot.engine.TraceInliningDetails=true"
--log-level TRACE. See
documentation
for the explanation of inlining decisions.Other than the subsections here, go through the existing documentation.
Main in engine-runner and Language in runtime. The former is the
embedder-side entry point, the latter the language-side one. They do a bit of
ping-pong through the polyglot APIs. That is unfortunate, as this API is
stringly typed. Therefore, chase the usages of method-name constants to jump
between the language-side implementations and the embedder-side calls.
Alternatively, step through the flow in a debugger.MainModule in language-server and RuntimeServerInstrument
in runtime. This is the entry point for IDE, with language/embedder
boundary as usual, but with a server-like message exchange instead of
polyglot API use.Look at Compiler in runtime. It is the main compiler class and the flow
should be straightforward. A high level overview is: the compiler alternates
between running module-local passes (currently in 3 groups) and global join
points, where information flows between modules.
There are a few very convoluted spots in the interpreter, with non-trivial design choices. Here's a list with some explanations:
ApplicationNode and follow the execute methods (or @Specializations).
There's a lot of them, but don't get too scared. It is also outlined
here.Context...).Standard.Builtins. See
the Builtins class
to see how that module is constructed. There's also a java-side
annotation-driven DSL for automatic generation of builtin method boilerplate.
See nodes in
this tree
to get an idea of how it works. Also
read the docsbt runtime-benchmarks/bench. Each run will
generate (or append to) the bench-report.xml file. See
Benchmarks for more information about the
benchmarking infrastructure.
Enso Language Support).sbt runtime-integration-tests/test. For newer functionalities, we prefer
adding tests to the Tests project in the standard library test. At this
point, Enso is mature enough to self-test.Talk to Dmitry! He's the main maintainer of this part.