enso/docs/debugger/runtime-debugging.md

70 lines
3.1 KiB
Markdown
Raw Normal View History

# Runtime (Engine) debugging
This section explains how to debug various parts of the Engine. By Engine, we
mean all the Java code located in the `runtime` SBT project, in `engine`
directory.
## Debugging source file evaluation
This subsection provides a guide how to debug a single Enso source file
evaluation. To evaluate a single source file, we use the _Engine distribution_
built with `buildEngineDistribution` command. Both of the following two options
starts the JVM in a debug mode. After the JVM is started in a debug mode, simply
attach the debugger to the JVM process at the specified port.
The first option is to invoke the engine distribution from SBT shell with:
```sh
sbt:enso> runEngineDistribution --debug --run ./test/Tests/src/Data/Numbers_Spec.enso
```
The second options is to pass in special JVM arguments when launching the
`bin/enso` from the engine distribution:
```bash
enso$ JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,server=n,address=5005 ./built-distribution/enso-engine-*/enso-*/bin/enso --run ./test/Tests/src/Data/Numbers_Spec.enso
```
### Tips and tricks
There is no simple mapping of the Enso source code to the engine's Java code, so
if you try to debug a specific expression, it might be a bit tricky. However,
the following steps should help you to skip all the irrelevant code and get to
the code you are interested in:
- To debug a method called `foo`, put a breakpoint in
`org.enso.interpreter.node.ClosureRootNode#execute` with a condition on
`this.name.contains("foo")`
- To debug a specific expression, put some _unique_ expression, like
`Debug.eval "1+1"`, in front of it and put a breakpoint in a Truffle node
corresponding to that unique expression, in this case that is
`org.enso.interpreter.node.expression.builtin.debug.DebugEvalNode`.
## Debugging annotation processors
The Engine uses annotation processors to generate some of the Java code, e.g.,
the builtin methods with `org.enso.interpreter.dsl.MethodProcessor`, or JMH
benchmark sources with `org.enso.benchmarks.processor.BenchProcessor`.
Annotation processors are invoked by the Java compiler (`javac`), therefore, we
need special instructions to attach the debugger to them.
Let's debug `org.enso.interpreter.dsl.MethodProcessor` as an example. The
following are the commands invoked in the `sbt` shell:
- `project runtime`
- `clean`
- Delete all the compiled class files along with all the generated sources by
the annotation processor. This ensures that the annotation processor will be
invoked.
- `set javacOptions += FrgaalJavaCompiler.debugArg`
- This sets a special flag that is passed to the frgaal Java compiler, which
in turn waits for the debugger to attach. Note that this setting is not
persisted and will be reset once the project is reloaded.
- `compile`
- Launches the Java compiler, which will wait for the debugger to attach. Put
a breakpoint in some class of `org.enso.interpreter.dsl` package. Wait for
the message in the console instructing to attach the debugger.
- To reset the `javacOptions` setting, either run
`set javacOptions -= FrgaalJavaCompiler.debugArg`, or reload the project with
`reload`.