diff options
author | Aaron Patterson <tenderlove@ruby-lang.org> | 2021-06-10 13:16:58 -0700 |
---|---|---|
committer | Alan Wu <XrXr@users.noreply.github.com> | 2021-10-20 18:19:36 -0400 |
commit | 46d5e10279b6f1cea46682b5a5da3a09c5ce0c07 (patch) | |
tree | 36d54adb88de3fb5a6c81bb64c16c49b6a97cf7e /yjit.rb | |
parent | f54e6e131099b5502f7d9be57f29bab11c70d841 (diff) |
Add graphviz output
This adds a method to blocks to get outgoing ids, then uses the outgoing
ids to generate a graphviz graph. Two methods were added to the Block
object. One method returns an id for the block, which is just the
address of the underlying block. The other method returns a list of
outgoing block ids. We can use Block#id in conjunction with
Block#outgoing_ids to construct a graph of blocks
Diffstat (limited to 'yjit.rb')
-rw-r--r-- | yjit.rb | 37 |
1 files changed, 37 insertions, 0 deletions
@@ -55,6 +55,43 @@ module YJIT def self.comments_for(start_address, end_address) Primitive.comments_for(start_address, end_address) end + + def self.graphviz_for(iseq) + iseq = RubyVM::InstructionSequence.of(iseq) + buff = '' + blocks = blocks_for(iseq) + buff << "digraph g {" + buff << " node [shape=record];" + blocks.each do |block| + buff << "b#{block.id} [label=\"#{disasm_block(block).gsub(/\n/, "\\l\n")}\"];" + block.outgoing_ids.each do |id| + buff << "b#{block.id} -> b#{id};" + end + end + buff << "}" + buff + end + + def self.disasm_block(block) + cs = YJIT::Disasm.new + comments = comments_for(block.address, block.address + block.code.length) + comment_idx = 0 + str = '' + cs.disasm(block.code, block.address).each do |i| + while (comment = comments[comment_idx]) && comment.address <= i.address + str << " ; #{comment.comment}\n" + comment_idx += 1 + end + + str << sprintf( + " %<address>08x: %<instruction>s\t%<details>s\n", + address: i.address, + instruction: i.mnemonic, + details: i.op_str + ) + end + str + end end # Return a hash for statistics generated for the --yjit-stats command line option. |