seafoam 0.8 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/bin/bgv2isabelle +1 -5
  3. data/bin/bgv2json +1 -5
  4. data/bin/cfg2asm +1 -5
  5. data/bin/seafoam +1 -5
  6. data/lib/seafoam/commands.rb +48 -31
  7. data/lib/seafoam/graal/pi.rb +18 -0
  8. data/lib/seafoam/graph.rb +9 -1
  9. data/lib/seafoam/graphviz_writer.rb +3 -0
  10. data/lib/seafoam/json_writer.rb +1 -3
  11. data/lib/seafoam/{annotators → passes}/fallback.rb +4 -4
  12. data/lib/seafoam/{annotators → passes}/graal.rb +43 -13
  13. data/lib/seafoam/passes/truffle.rb +58 -0
  14. data/lib/seafoam/passes.rb +61 -0
  15. data/lib/seafoam/version.rb +1 -1
  16. data/lib/seafoam.rb +5 -4
  17. metadata +23 -60
  18. data/.github/probots.yml +0 -2
  19. data/.github/workflows/workflows.yml +0 -40
  20. data/.gitignore +0 -6
  21. data/.rubocop.yml +0 -37
  22. data/.ruby-version +0 -1
  23. data/.seafoam/config +0 -1
  24. data/CODE_OF_CONDUCT.md +0 -128
  25. data/CONTRIBUTING.md +0 -5
  26. data/Gemfile +0 -2
  27. data/Gemfile.lock +0 -59
  28. data/LICENSE.md +0 -7
  29. data/README.md +0 -378
  30. data/demos/box-unbox-stats +0 -65
  31. data/docs/annotators.md +0 -43
  32. data/docs/bgv.md +0 -294
  33. data/docs/getting-graphs.md +0 -63
  34. data/docs/images/igv.png +0 -0
  35. data/docs/images/seafoam.png +0 -0
  36. data/docs/images/spotlight-igv.png +0 -0
  37. data/docs/images/spotlight-seafoam.png +0 -0
  38. data/docs/json.md +0 -35
  39. data/examples/Fib.java +0 -24
  40. data/examples/MatMult.java +0 -39
  41. data/examples/fib-java.bgv.gz +0 -0
  42. data/examples/fib.js +0 -15
  43. data/examples/fib.rb +0 -15
  44. data/examples/identity.rb +0 -13
  45. data/examples/java/Irreducible.class +0 -0
  46. data/examples/java/Irreducible.j +0 -35
  47. data/examples/java/IrreducibleDecompiled.java +0 -21
  48. data/examples/java/JavaExamples.java +0 -418
  49. data/examples/matmult.rb +0 -29
  50. data/examples/overflow.rb +0 -13
  51. data/examples/ruby/clamps.rb +0 -20
  52. data/examples/ruby/graal.patch +0 -15
  53. data/examples/ruby/ruby_examples.rb +0 -278
  54. data/lib/seafoam/annotators.rb +0 -54
  55. data/lib/seafoam/config.rb +0 -34
  56. data/seafoam.gemspec +0 -22
  57. data/spec/seafoam/annotators/fallback_spec.rb +0 -69
  58. data/spec/seafoam/annotators/graal_spec.rb +0 -96
  59. data/spec/seafoam/annotators_spec.rb +0 -61
  60. data/spec/seafoam/bgv/bgv_parser_spec.rb +0 -167
  61. data/spec/seafoam/binary/io_binary_reader_spec.rb +0 -176
  62. data/spec/seafoam/cfg/cfg_parser_spec.rb +0 -21
  63. data/spec/seafoam/cfg/disassembler_spec.rb +0 -32
  64. data/spec/seafoam/command_spec.rb +0 -314
  65. data/spec/seafoam/graph_spec.rb +0 -172
  66. data/spec/seafoam/graphviz_writer_spec.rb +0 -63
  67. data/spec/seafoam/json_writer_spec.rb +0 -14
  68. data/spec/seafoam/spec_helpers.rb +0 -34
  69. data/spec/seafoam/spotlight_spec.rb +0 -38
  70. data/tools/render-all +0 -36
data/README.md DELETED
@@ -1,378 +0,0 @@
1
- # Seafoam
2
-
3
- *Seafoam* is a tool for working with compiler graphs. It's designed primarily
4
- for working with the graph files dumped by the GraalVM compiler, such as in
5
- TruffleRuby, but it could be used with other compilers and graph dump file
6
- formats.
7
-
8
- The *Ideal Graph Visualizer*, or *IGV*, is the tool usually used to work with
9
- GraalVM compiler graphs. Seafoam aims to solve several problems with IGV. Unlike
10
- IGV, Seafoam:
11
-
12
- * is open source and can be used according to the MIT license
13
- * supports gzip-compressed BGV files
14
- * is able to some extent seek BGV files to load specific graphs without loading the rest of the file
15
- * has a command-line interface
16
- * can be used as a library
17
- * has easy PDF, SVG, PNG and JSON output
18
- * is designed for accessibility
19
- * looks prettier, in our opinion
20
-
21
- Additionally, Seafoam adds:
22
-
23
- * support for disassembling CFG files
24
-
25
- Admittedly, Seafoam does not yet have:
26
-
27
- * an interactive user interface
28
- * diffing of graphs
29
- * breaking of edges for very congested graphs
30
- * the same speed in rendering big graphs - Seafoam is best suited for looking at graphs before lowering, which is what language developers are usually doing, or use spotlight
31
-
32
- ## Seafoam compared to IGV
33
-
34
- <p>
35
- <img src="docs/images/seafoam.png" width="350">
36
- <img src="docs/images/igv.png" width="350">
37
- </p>
38
-
39
- ## Installation
40
-
41
- ### macOS
42
-
43
- ```
44
- % brew install graphviz
45
- % gem install seafoam
46
- % seafoam --version
47
- seafoam 0.1
48
- ```
49
-
50
- ### Ubuntu
51
-
52
- ```
53
- % sudo apt-get install ruby graphviz
54
- % gem install seafoam
55
- % seafoam --version
56
- seafoam 0.1
57
- ```
58
-
59
- ### RedHat
60
-
61
- ```
62
- % sudo yum install ruby graphviz
63
- % gem install seafoam
64
- % seafoam --version
65
- seafoam 0.1
66
- ```
67
-
68
- ### Capstone
69
-
70
- To use the `cfg2asm` disassembler, you'll then need to install Capstone.
71
-
72
- ```
73
- % brew install capstone # macOS
74
- % sudo apt-get install libcapstone3 # Ubuntu
75
- ```
76
-
77
- ## Quick-start demo
78
-
79
- ```
80
- % seafoam examples/fib-java.bgv:0 render
81
- ```
82
-
83
- ## Getting compiler graphs
84
-
85
- If you are just experimenting, there are example graphs such as
86
- `examples/fib-java.bgv`.
87
-
88
- This is just a quick summary - see more information on
89
- [getting graphs out of compilers](docs/getting-graphs.md).
90
-
91
- ### GraalVM for Java
92
-
93
- ```
94
- % javac Fib.java
95
- % java -XX:CompileOnly=::fib -Dgraal.Dump=:2 Fib 14
96
- ```
97
-
98
- ### GraalVM Native Image
99
-
100
- ```
101
- % native-image -H:Dump=:2 -H:MethodFilter=fib Fib
102
- ```
103
-
104
- ### TruffleRuby and other Truffle languages
105
-
106
- ```
107
- % ruby --experimental-options --engine.CompileOnly=fib --engine.Inlining=false --engine.OSR=false --vm.Dgraal.Dump=Truffle:2 fib.rb 14
108
- ```
109
-
110
- You will usually want to look at the *After TruffleTier* graph.
111
-
112
- ## Name syntax
113
-
114
- When using a command-line interface, Seafoam refers to
115
- `file.bgv[:graph][:node[-edge]]`, where `file.bgv` is a file, `graph` is a graph
116
- index, `node` is a node index, and `to` is another node index to form an edge
117
- from `node` to another node `edge`.
118
-
119
- Note that a *graph ID* is an ID found in BGV files, but is not unique. A
120
- *graph index* is what we use in names, and is unique.
121
-
122
- ## Use cases
123
-
124
- #### Print information about a file
125
-
126
- ```
127
- % seafoam examples/fib-java.bgv info
128
- BGV 6.1
129
- ```
130
-
131
- #### List graphs in a file
132
-
133
- ```
134
- % seafoam examples/fib-java.bgv list
135
- examples/fib-java.bgv:0 2:Fib.fib(int)/After phase org.graalvm.compiler.java.GraphBuilderPhase
136
- examples/fib-java.bgv:1 2:Fib.fib(int)/After phase org.graalvm.compiler.phases.PhaseSuite
137
- examples/fib-java.bgv:2 2:Fib.fib(int)/After phase org.graalvm.compiler.phases.common.DeadCodeEliminationPhase
138
- examples/fib-java.bgv:3 2:Fib.fib(int)/After parsing
139
- examples/fib-java.bgv:4 2:Fib.fib(int)/After phase org.graalvm.compiler.phases.common.CanonicalizerPhase
140
- examples/fib-java.bgv:5 2:Fib.fib(int)/After phase org.graalvm.compiler.phases.common.inlining.InliningPhase
141
- ...
142
- ```
143
-
144
- #### Search for strings in a graph, or node or edge within a graph
145
-
146
- ```
147
- % seafoam examples/fib-java.bgv:0 search Start
148
- examples/fib-java.bgv:0:0 ...node_class":"org.graalvm.compiler.nodes.StartNode","name_template":"Start","inputs":[...
149
- examples/fib-java.bgv:0:0 ...piler.nodes.StartNode","name_template":"Start","inputs":[{"direct":true,"name":"state...
150
- ```
151
-
152
- #### Print edges of a graph, or node or edge within a graph
153
-
154
- ```
155
- % seafoam examples/fib-java.bgv:0 edges
156
- 22 nodes, 30 edges
157
- % seafoam examples/fib-java.bgv:0:13 edges
158
- Input:
159
- 13 (Call Fib.fib) <-() 6 (Begin)
160
- 13 (Call Fib.fib) <-() 14 (@{:declaring_class=>"Fib", :method_name=>"fib", :signature=>{:args=>["I"], :ret=>"I"}, :modifiers=>9}:13)
161
- 13 (Call Fib.fib) <-() 12 (MethodCallTarget)
162
- Output:
163
- 13 (Call Fib.fib) ->() 18 (Call Fib.fib)
164
- 13 (Call Fib.fib) ->(values) 14 (@{:declaring_class=>"Fib", :method_name=>"fib", :signature=>{:args=>["I"], :ret=>"I"}, :modifiers=>9}:13)
165
- 13 (Call Fib.fib) ->(values) 19 (@{:declaring_class=>"Fib", :method_name=>"fib", :signature=>{:args=>["I"], :ret=>"I"}, :modifiers=>9}:19)
166
- 13 (Call Fib.fib) ->(x) 20 (+)
167
- % seafoam examples/fib-java.bgv:0:13-20 edges
168
- 13 (Call Fib.fib) ->(x) 20 (+)
169
- ```
170
-
171
- #### Print properties of a file, graph, or node or edge within a graph
172
-
173
- ```
174
- % seafoam examples/fib-java.bgv:0 props
175
- {
176
- "group": [
177
- {
178
- "name": "2:Fib.fib(int)",
179
- "short_name": "2:Fib.fib(int)",
180
- "method": null,
181
- ...
182
- % seafoam examples/fib-java.bgv:0:13 props
183
- {
184
- "nodeSourcePosition": {
185
- "method": {
186
- "declaring_class": "Fib",
187
- "method_name": "fib",
188
- "signature": {
189
- ...
190
- % seafoam examples/fib-java.bgv:0:13-20 props
191
- {
192
- "direct": true,
193
- "name": "x",
194
- "type": "Value"
195
- }
196
- ```
197
-
198
- #### Print node source information
199
-
200
- ```
201
- % seafoam examples/fib-ruby.bgv:8:2443 source
202
- java.lang.Math#addExact
203
- org.truffleruby.core.numeric.IntegerNodes$AddNode#add
204
- org.truffleruby.core.numeric.IntegerNodesFactory$AddNodeFactory$AddNodeGen#executeAdd
205
- org.truffleruby.core.inlined.InlinedAddNode#intAdd
206
- org.truffleruby.core.inlined.InlinedAddNodeGen#execute
207
- org.truffleruby.language.control.IfElseNode#execute
208
- org.truffleruby.language.control.SequenceNode#execute
209
- org.truffleruby.language.arguments.CheckArityNode#execute
210
- org.truffleruby.language.control.SequenceNode#execute
211
- org.truffleruby.language.methods.CatchForMethodNode#execute
212
- org.truffleruby.language.methods.ExceptionTranslatingNode#execute
213
- org.truffleruby.language.RubyRootNode#execute
214
- org.graalvm.compiler.truffle.runtime.OptimizedCallTarget#executeRootNode
215
- org.graalvm.compiler.truffle.runtime.OptimizedCallTarget#profiledPERoot
216
- ```
217
-
218
- #### Render a graph
219
-
220
- Render a graph as a PDF image and have it opened automatically.
221
-
222
- ```
223
- % seafoam examples/fib-java.bgv:0 render
224
- ```
225
-
226
- Render a graph showing just a few nodes and those surrounding them, similar to
227
- the IGV feature of gradually revealing nodes.
228
-
229
- ```
230
- % seafoam examples/fib-java.bgv:0 render --spotlight 13,20
231
- ```
232
-
233
- <p>
234
- <img src="docs/images/spotlight-seafoam.png" width="200">
235
- <img src="docs/images/spotlight-igv.png" width="350">
236
- </p>
237
-
238
- `render` supports these options:
239
-
240
- * `--out filename.pdf` or `.pdf`, `.svg`, `.png`, `.dot`
241
- * `--option key value` for custom annotators
242
-
243
- #### Convert a file
244
-
245
- Convert a BGV file to the Isabelle graph format.
246
-
247
- ```
248
- % bgv2isabelle examples/fib-java.bgv
249
- graph0 = # 2:Fib.fib(int)/After phase org.graalvm.compiler.java.GraphBuilderPhase
250
- (add_node 0 StartNode [2] [8]
251
- (add_node 1 (ParameterNode 0) [] [2, 5, 9, 11, 14, 16]
252
- (add_node 2 FrameState [1] [0]
253
- (add_node 3 (ConstantNode 1) [] []
254
- (add_node 4 (ConstantNode 2) [] [5]
255
- (add_node 5 IntegerLessThanNode [1, 4] [8]
256
- (add_node 6 BeginNode [8] [13]
257
- (add_node 7 BeginNode [8] [9]
258
- (add_node 8 IfNode [0, 5] [7, 6]
259
- ...
260
- ```
261
-
262
- Convert a BGV file to JSON.
263
-
264
- ```
265
- % bgv2json examples/fib-java.bgv
266
- graph0 = # 2:Fib.fib(int)/After phase org.graalvm.compiler.java.GraphBuilderPhase
267
- (add_node 0 StartNode [2] [8]
268
- (add_node 1 (ParameterNode 0) [] [2, 5, 9, 11, 14, 16]
269
- (add_node 2 FrameState [1] [0]
270
- (add_node 3 (ConstantNode 1) [] []
271
- (add_node 4 (ConstantNode 2) [] [5]
272
- (add_node 5 IntegerLessThanNode [1, 4] [8]
273
- (add_node 6 BeginNode [8] [13]
274
- (add_node 7 BeginNode [8] [9]
275
- (add_node 8 IfNode [0, 5] [7, 6]
276
- ...
277
- ```
278
-
279
- #### Disassembling
280
-
281
- ```
282
- % cfg2asm examples/java/exampleArithOperator.cfg
283
- [examples/java/exampleArithOperator.cfg]
284
- ;Comment 0: 3
285
- ;Comment 0: 1
286
- 0x112e2f660: nop dword ptr [rax + rax]
287
- ;Comment 5: block B0 null
288
- ;Comment 5: 0 [rsi|DWORD, rdx|DWORD, rbp|QWORD] = LABEL numbPhis: 0 align: false label: ?
289
- ;Comment 5: 4 [] = HOTSPOTLOCKSTACK frameMapBuilder: org.graalvm.compiler.lir.amd64.AMD64FrameMapBuilder@143082de0 slotKind: QWORD
290
- ;Comment 5: 10 rsi|DWORD = ADD (x: rsi|DWORD, y: rdx|DWORD) size: DWORD
291
- 0x112e2f665: add esi, edx
292
- ;Comment 7: 12 rax|DWORD = MOVE rsi|DWORD moveKind: DWORD
293
- 0x112e2f667: mov eax, esi
294
- ;Comment 9: 14 RETURN (savedRbp: rbp|QWORD, value: rax|DWORD) isStub: false requiresReservedStackAccessCheck: false thread: r15 scratchForSafepointOnReturn: rcx config: org.graalvm.compiler.hotspot.GraalHotSpotVMConfig@137f187d8
295
- ;Comment 9: 12
296
- 0x112e2f669: test dword ptr [rip - 0x46c4669], eax
297
- 0x112e2f66f: vzeroupper
298
- 0x112e2f672: ret
299
- ...
300
- ```
301
-
302
- ## Options for GraalVM graphs
303
-
304
- * `--show-frame-state` shows frame state nodes, which are hidden by default
305
- * `--hide-floating` hides nodes that aren't fixed by control flow
306
- * `--no-reduce-edges` turns off the option to reduce the number of edges by inlining simple nodes above their users
307
- * `--draw-blocks` to draw basic block information if available
308
-
309
- ## Configuration
310
-
311
- Seafoam loads and runs a Ruby script called `~/.seafoam/config` in the first
312
- directory it finds starting with the current working directory and moving up.
313
- You can require or configure extra [annotators](docs/annotators.md) in this
314
- file.
315
-
316
- ## Debugging
317
-
318
- Exception backtraces are printed if `$DEBUG` (`-d`) is set.
319
-
320
- Use `seafoam file.bgv debug` to debug file parsing.
321
-
322
- ## More documentation
323
-
324
- * [Graph annotators](docs/annotators.md)
325
- * [Details of the BGV file format](docs/bgv.md)
326
- * [How to get graphs from various compilers](docs/getting-graphs.md)
327
-
328
- ## Frequently asked questions
329
-
330
- #### Why is it called *Seafoam*?
331
-
332
- GraalVM graphs are *seas of nodes*. Seafoam is a shade of green, and Seafoam was
333
- written at Shopify, which has green as a brand colour. Graphs can sometimes be
334
- very complicated, appearing like a foam without any structure - Seafoam tries to
335
- help you make sense of it all.
336
-
337
- #### What do you mean by *graphs*, and *seas* or *soups* of nodes?
338
-
339
- Graphs, as in edges and nodes, are the data structure some compilers use to
340
- represent your program while they're compiling it. It's a form of *intermediate
341
- representation*. Graphs are how the compiler understands the programs and if the
342
- compiler isn't doing what you want you need to look at the graph and make sense
343
- of it. Some graphs are loosely structured and large, making them like a sea or
344
- soup of nodes.
345
-
346
- #### Doesn't *reduce edges* actually introduce more edges?
347
-
348
- Yes, but they're shorter edges, and it achieves the intended effect of less
349
- edges crossing over the graph.
350
-
351
- ## Related work
352
-
353
- The graph layout algorithm we use, via Graphviz, is
354
-
355
- * E. R. Gansner, et al, [*A Technique for Drawing Directed Graphs*](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.3.8982), IEEE Transactions on Software Engineering, 1993
356
-
357
- IGV is the existing tool for working with Graal graphs. It uses a *hierarchical*
358
- layout algorithm, rather than the *force directed* algorithm we use when we use
359
- Graphviz. It's based on the NetBeans IDE platform. It's related to the *C1
360
- Visualiser*, for control-flow graphs. The C1 Visualiser can also be used with
361
- Graal as the backend of Graal is similar enough to C1. IGV is closed-source and
362
- available under a proprietary licence.
363
-
364
- * T. Würthinger, [*Visualization of Program Dependence Graphs*](http://www.ssw.uni-linz.ac.at/Research/Papers/Wuerthinger07Master/), Master Thesis, Linz 2007
365
- * T. Würthinger, [*Visualization of Java Control Flow Graphs*](http://www.ssw.uni-linz.ac.at/General/Staff/TW/Wuerthinger06Bachelor.pdf), Bachelor Thesis, Linz 2006
366
-
367
- [*Turbolizer*][turbolizer] is a similar tool for the intermediate representation
368
- in the V8 JavaScript compiler.
369
-
370
- [turbolizer]: https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/tools/turbolizer
371
-
372
- ## Author
373
-
374
- Seafoam was written by Chris Seaton at Shopify, chris.seaton@shopify.com.
375
-
376
- ## License
377
-
378
- MIT
@@ -1,65 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # This demo analyses a directory full of graphs and looks for how many box nodes
4
- # take their value directly from an unbox node.
5
-
6
- require 'seafoam'
7
-
8
- box_nodes_count = 0
9
- box_nodes_from_unbox_count = 0
10
-
11
- graph_count = 0
12
- graph_match_count = 0
13
-
14
- ARGV.each do |dir|
15
- Dir.glob(['*.bgv', '*.bgv.gz'], base: dir) do |file|
16
- parser = Seafoam::BGV::BGVParser.new(File.join(dir, file))
17
- parser.read_file_header
18
- parser.skip_document_props
19
-
20
- loop do
21
- index, = parser.read_graph_preheader
22
- break unless index
23
-
24
- parser.skip_graph_header
25
- graph = parser.read_graph
26
-
27
- contains_box_unbox = false
28
-
29
- graph.nodes.each_value do |node|
30
- next unless node.props.dig(:node_class, :node_class).start_with?('org.graalvm.compiler.nodes.extended.BoxNode')
31
-
32
- box_node = node
33
- box_nodes_count += 1
34
- value_edge = node.edges.find { |e| e.props[:name] == 'value' }
35
- raise unless value_edge
36
-
37
- value_node = value_edge.from
38
- next unless value_node.props.dig(:node_class, :node_class).start_with?('org.graalvm.compiler.nodes.extended.UnboxNode')
39
-
40
- unbox_node = value_node
41
- box_nodes_from_unbox_count += 1
42
- contains_box_unbox = true
43
- puts "seafoam '#{File.join(dir, file)}:#{index}' render --spotlight #{box_node.id},#{unbox_node.id}"
44
- end
45
-
46
- graph_count += 1
47
- graph_match_count += 1 if contains_box_unbox
48
- end
49
- end
50
- end
51
-
52
- if box_nodes_count.positive?
53
- box_nodes_percent = (box_nodes_from_unbox_count / box_nodes_count.to_f) * 100
54
- else
55
- box_nodes_percent = 0.0
56
- end
57
-
58
- if graph_count.positive?
59
- graph_percent = (graph_match_count / graph_count.to_f) * 100
60
- else
61
- graph_percent = 0.0
62
- end
63
-
64
- puts " How many boxes take a value from an unbox? #{box_nodes_percent.round(1)}%"
65
- puts "How many graphs contain at least one box-unbox? #{graph_percent.round(1)}%"
data/docs/annotators.md DELETED
@@ -1,43 +0,0 @@
1
- # Annotators
2
-
3
- The model of Seafoam is that it is a directed graph, with nodes annotated with a
4
- bag of key-value properties. When graphs are read they'll have some initial
5
- properties. Seafoam may add more properties. The output routines then draw the
6
- graph using the graph structure itself and also the properties.
7
-
8
- *Annotators* are routines that add extra properties to graphs to help the user
9
- understand them. They usually have knowledge of how the graph is structured, and
10
- use this to make the graph easier to read or to make important information in
11
- them stand out.
12
-
13
- We call properties with symbol keys *annotations*, as they're added by the
14
- annotators.
15
-
16
- Annotators are similar to filters in IGV.
17
-
18
- Appropriate annotators are automatically selected and applied to graphs.
19
-
20
- The rendering commands recognize these annotations, so annotators will probably
21
- want to add them:
22
-
23
- * `:label` on nodes and edges
24
- * `:out_annotation` on nodes
25
- * `:hidden` on nodes only, to not show them (*remove frame state* for example in IGV terminology)
26
- * `:inlined` on nodes only, to indicate the node should be shown immediately above each node using it (*reduce edges* in IGV terminology)
27
- * `:kind` on nodes only, which can be `info`, `input`, `control`, `effect`, `virtual`, `calc`, `guard`, or `other`
28
- * `:kind` on edges only, which can be `info`, `control`, `loop`, or `data`
29
- * `:reverse` on edges only
30
- * `:spotlight` for nodes as part of spotlighting (`lit` are shown, `shaded` are shown but greyed out, and edges from `shaded` to `:hidden` nodes are also shown greyed out)
31
-
32
- Seafoam ships with an annotator for generic GraalVM graphs. If you work with a
33
- different compiler you'll probably want to write your own annotators - subclass
34
- `Seafoam::Annotator` and implement `#annotate(graph)`. You can add custom
35
- annotators by requiring them in your `.seafoam/config`. All subclasses of
36
- `Annotator` will be found, so you just need to define the subclass.
37
-
38
- A fallback annotator, run after all others, just labels the node with the
39
- `'label'` property if there is one.
40
-
41
- Options for annotations can be set on the command line with `--option key
42
- value`. Some options are built into Seafoam commands, like `--show-frame-state`,
43
- but they're doing the same thing as `--option hide_frame_state false`.