Compilers are not magical beasts. They are steampunk machines grinding your perfectly structured source into incomprehensible mess of native code. The better the compiler - the finer the grind and stronger our performance espresso. What’s not to like?
If you ever had to look at V8’s IR you probably know that it dumps it out in form
that C1Visualizer, visualization tool created for C1 HotSpot compiler, can digest. It makes exploration of
hydrogen.cfg much more comfortable but it does not make you smile.
I wrote the tool for my own use, so I put little effort into thinking about UX or designing a UI. Frankly speaking designing UI is harder than writing a compiler. If you start using IRHydra and get ideas how to improve things don’t hesitate to send me comments, issues and patches.
IRHydra is extracting information from the dumps that were not necessarily intended to be machine readable. Thus currently it can misinterpret information or loose some of it. Take it with a grain of salt.
For me the most important features of this tools are its universal availability (no need to install anything just browse to the page) and the fact that I can easily extend it to do my bidding if I need to perform some highly custom highlighting over IR.
How does it work?
Quite simply: you take compilation artifacts produced by V8 or Dart VM and view them in the browser. IRHydra does not have any server component, it uses
FileReader API so your files are not uploaded anywhere they are parsed and displayed locally.
The way to obtain compilation artifacts depends on your platform. For example when using node.js you can do:
node --trace-hydrogen \ --trace-deopt \ --code-comments \ --print-opt-code \ benchmark/http_simple.js > code.asm
hydrogen.cfg will contain intermediate representation generated by V8’s optimizing compiler and
code.asm will contain all information dumped by V8 to standard output (disassembly and deoptimizations).
By default release version of V8 is built with disassembler disabled. To enable it you might have to reconfigure and rebuild your node:
GYP_DEFINES="v8_enable_disassembler=1 v8_object_print=1" ./configure make
Once you feed these files into IRHydra it’ll show you a list of optimized function and place a red marker near those that deoptimized. IRHydra is using names to match deoptimizations to compiled functions so it might mismatch some (especially if you have multiple functions with the same name).
Selecting function’s compilation phase will display generated IR and control flow graph on the right pane. Some important features of the IR viewer:
IR is cross-referenced: hovering over SSA variable name or block name will display referenced instruction or the whole block.
If possible deoptimizations are matched to the IR instructions where they actually occurred. This instructions are annotated with deopt marker.
On ia32 it is usually possible to match deoptimization to the lithium instruction just using information from the
--trace-deopt --code-comments output. However as one can notice from the picture above on x64 architecture this output lies and IRHydra requires either
hydrogen.cfg produced by V8 not older than 3.17 or full optimized code disassembly to perform matching.
Additionally viewer supports attaching descriptions to HIR and LIR instructions to help someone not intimately familiar with V8 to understand the reason behind the deoptimization.
Only a handful of instructions is annotated right now but don’t hesitate to file bugs against those that are not. If you are familiar with V8 IR you can even send me patches against descriptions.html.
When available the disassembly can be spliced into the IR.
In future I plan to improve disassembly view by providing better highlighting for it and implementing some tools to highlight “data-flow” between registers.
Control flow graph
Finally the control flow graph is available in all its beauty. It is connected to the main IR view for easy navigation and overview. Loop blocks are dyed red from a Brewer palette: color becomes more intense as loop nesting depth increases.
Graph layout itself is performed by a part of Draw2d library semi-automatically translated from Java to Dart. Translation was done by a very early version of the java2dart tool and might have introduced some bugs, but majority of graphs I tried it on seem to look fine or almost fine :-)
Using IRHydra with Dart VM
As indicated above both V8 and Dart VM are supported. In fact IRHydra is even more useful for Dart VM because it does not output anything like
hydrogen.cfg and you are bound to explore IR in your favorite text editor.
To obtain compilation artifacts you need to run Dart VM in the following way:
dart --print-flow-graph-optimized \ --disassemble-optimized \ --code-comments \ benchmark.dart > code.asm
All information will be dumped to standard output. If you load
code.asm into IRHydra you’ll be able to explore it in the same way (including disassembly and graph views) as you can explore V8 IRs:
The only feature not supported for Dart VM is deoptimization markers because I did not yet have any need for it.