seafoam 0.3 → 0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/workflows.yml +40 -0
  3. data/.gitignore +0 -1
  4. data/.rubocop.yml +1 -1
  5. data/.ruby-version +1 -1
  6. data/Gemfile.lock +59 -0
  7. data/README.md +76 -3
  8. data/bin/bgv2isabelle +16 -45
  9. data/bin/bgv2json +18 -36
  10. data/bin/cfg2asm +24 -0
  11. data/bin/seafoam +1 -1
  12. data/demos/box-unbox-stats +65 -0
  13. data/docs/bgv.md +2 -1
  14. data/docs/getting-graphs.md +8 -0
  15. data/examples/Fib.java +1 -1
  16. data/examples/fib-java.bgv.gz +0 -0
  17. data/examples/fib.js +1 -1
  18. data/examples/java/JavaExamples.java +1 -1
  19. data/examples/ruby/clamps.rb +20 -0
  20. data/examples/ruby/graal.patch +15 -0
  21. data/examples/ruby/ruby_examples.rb +278 -0
  22. data/lib/seafoam.rb +5 -1
  23. data/lib/seafoam/annotators/graal.rb +1 -1
  24. data/lib/seafoam/bgv/bgv_parser.rb +10 -2
  25. data/lib/seafoam/cfg/cfg_parser.rb +93 -0
  26. data/lib/seafoam/cfg/disassembler.rb +70 -0
  27. data/lib/seafoam/commands.rb +190 -30
  28. data/lib/seafoam/graal/source.rb +23 -0
  29. data/lib/seafoam/graph.rb +25 -1
  30. data/lib/seafoam/graphviz_writer.rb +21 -2
  31. data/lib/seafoam/isabelle_writer.rb +46 -0
  32. data/lib/seafoam/json_writer.rb +58 -0
  33. data/lib/seafoam/version.rb +1 -1
  34. data/seafoam.gemspec +4 -2
  35. data/spec/seafoam/annotators/graal_spec.rb +7 -7
  36. data/spec/seafoam/bgv/bgv_parser_spec.rb +13 -3
  37. data/spec/seafoam/cfg/cfg_parser_spec.rb +21 -0
  38. data/spec/seafoam/cfg/disassembler_spec.rb +32 -0
  39. data/spec/seafoam/command_spec.rb +86 -40
  40. data/spec/seafoam/json_writer_spec.rb +14 -0
  41. data/spec/seafoam/spec_helpers.rb +4 -0
  42. data/spec/seafoam/spotlight_spec.rb +1 -1
  43. data/tools/render-all +2 -2
  44. metadata +33 -96
  45. data/.github/workflows/rubocop.yml +0 -10
  46. data/.github/workflows/specs.yml +0 -19
  47. data/examples/fib-java.bgv +0 -0
  48. data/examples/fib-js.bgv +0 -0
  49. data/examples/fib-ruby.bgv +0 -0
  50. data/examples/identity.bgv +0 -0
  51. data/examples/java/exampleArithOperator.bgv +0 -0
  52. data/examples/java/exampleArithOperator.cfg +0 -925
  53. data/examples/java/exampleArrayAllocation.bgv +0 -0
  54. data/examples/java/exampleArrayAllocation.cfg +0 -5268
  55. data/examples/java/exampleArrayRead.bgv +0 -0
  56. data/examples/java/exampleArrayRead.cfg +0 -2263
  57. data/examples/java/exampleArrayWrite.bgv +0 -0
  58. data/examples/java/exampleArrayWrite.cfg +0 -2315
  59. data/examples/java/exampleCatch.bgv +0 -0
  60. data/examples/java/exampleCatch.cfg +0 -4150
  61. data/examples/java/exampleCompareOperator.bgv +0 -0
  62. data/examples/java/exampleCompareOperator.cfg +0 -1109
  63. data/examples/java/exampleDoubleSynchronized.bgv +0 -0
  64. data/examples/java/exampleDoubleSynchronized.cfg +0 -26497
  65. data/examples/java/exampleExactArith.bgv +0 -0
  66. data/examples/java/exampleExactArith.cfg +0 -1888
  67. data/examples/java/exampleFieldRead.bgv +0 -0
  68. data/examples/java/exampleFieldRead.cfg +0 -1228
  69. data/examples/java/exampleFieldWrite.bgv +0 -0
  70. data/examples/java/exampleFieldWrite.cfg +0 -1102
  71. data/examples/java/exampleFor.bgv +0 -0
  72. data/examples/java/exampleFor.cfg +0 -3936
  73. data/examples/java/exampleFullEscape.bgv +0 -0
  74. data/examples/java/exampleFullEscape.cfg +0 -5893
  75. data/examples/java/exampleIf.bgv +0 -0
  76. data/examples/java/exampleIf.cfg +0 -2462
  77. data/examples/java/exampleIfNeverTaken.bgv +0 -0
  78. data/examples/java/exampleIfNeverTaken.cfg +0 -2476
  79. data/examples/java/exampleInstanceOfManyImpls.bgv +0 -0
  80. data/examples/java/exampleInstanceOfManyImpls.cfg +0 -6391
  81. data/examples/java/exampleInstanceOfOneImpl.bgv +0 -0
  82. data/examples/java/exampleInstanceOfOneImpl.cfg +0 -2604
  83. data/examples/java/exampleIntSwitch.bgv +0 -0
  84. data/examples/java/exampleIntSwitch.cfg +0 -3121
  85. data/examples/java/exampleInterfaceCallManyImpls.bgv +0 -0
  86. data/examples/java/exampleInterfaceCallManyImpls.cfg +0 -1358
  87. data/examples/java/exampleInterfaceCallOneImpl.bgv +0 -0
  88. data/examples/java/exampleInterfaceCallOneImpl.cfg +0 -3859
  89. data/examples/java/exampleLocalInstanceOf.bgv +0 -0
  90. data/examples/java/exampleLocalInstanceOf.cfg +0 -5276
  91. data/examples/java/exampleLocalSynchronized.bgv +0 -0
  92. data/examples/java/exampleLocalSynchronized.cfg +0 -1364
  93. data/examples/java/exampleLocalVariables.bgv +0 -0
  94. data/examples/java/exampleLocalVariables.cfg +0 -1195
  95. data/examples/java/exampleLocalVariablesState.bgv +0 -0
  96. data/examples/java/exampleLocalVariablesState.cfg +0 -1673
  97. data/examples/java/exampleNestedWhile.bgv +0 -0
  98. data/examples/java/exampleNestedWhile.cfg +0 -15499
  99. data/examples/java/exampleNestedWhileBreak.bgv +0 -0
  100. data/examples/java/exampleNestedWhileBreak.cfg +0 -11162
  101. data/examples/java/exampleNoEscape.bgv +0 -0
  102. data/examples/java/exampleNoEscape.cfg +0 -974
  103. data/examples/java/exampleObjectAllocation.bgv +0 -0
  104. data/examples/java/exampleObjectAllocation.cfg +0 -5287
  105. data/examples/java/examplePartialEscape.bgv +0 -0
  106. data/examples/java/examplePartialEscape.cfg +0 -7042
  107. data/examples/java/examplePhi.bgv +0 -0
  108. data/examples/java/examplePhi.cfg +0 -3227
  109. data/examples/java/exampleReducible.bgv +0 -0
  110. data/examples/java/exampleReducible.cfg +0 -5578
  111. data/examples/java/exampleSimpleCall.bgv +0 -0
  112. data/examples/java/exampleSimpleCall.cfg +0 -1435
  113. data/examples/java/exampleStamp.bgv +0 -0
  114. data/examples/java/exampleStamp.cfg +0 -913
  115. data/examples/java/exampleStaticCall.bgv +0 -0
  116. data/examples/java/exampleStaticCall.cfg +0 -1154
  117. data/examples/java/exampleStringSwitch.bgv +0 -0
  118. data/examples/java/exampleStringSwitch.cfg +0 -15377
  119. data/examples/java/exampleSynchronized.bgv +0 -0
  120. data/examples/java/exampleSynchronized.cfg +0 -26027
  121. data/examples/java/exampleThrow.bgv +0 -0
  122. data/examples/java/exampleThrow.cfg +0 -780
  123. data/examples/java/exampleThrowCatch.bgv +0 -0
  124. data/examples/java/exampleThrowCatch.cfg +0 -744
  125. data/examples/java/exampleUnsafeRead.bgv +0 -0
  126. data/examples/java/exampleUnsafeRead.cfg +0 -912
  127. data/examples/java/exampleUnsafeWrite.bgv +0 -0
  128. data/examples/java/exampleUnsafeWrite.cfg +0 -962
  129. data/examples/java/exampleWhile.bgv +0 -0
  130. data/examples/java/exampleWhile.cfg +0 -3936
  131. data/examples/java/exampleWhileBreak.bgv +0 -0
  132. data/examples/java/exampleWhileBreak.cfg +0 -5963
  133. data/examples/matmult-java.bgv +0 -0
  134. data/examples/matmult-ruby.bgv +0 -0
  135. data/examples/overflow.bgv +0 -0
  136. data/spec/seafoam/bgv/fixtures/not.bgv +0 -1
  137. data/spec/seafoam/bgv/fixtures/unsupported.bgv +0 -1
data/docs/bgv.md CHANGED
@@ -57,7 +57,8 @@ GraphBody {
57
57
  Props props
58
58
  sint32 nodes_count
59
59
  Node[nodes_count] nodes
60
- Blocks blocks
60
+ sint32 blocks_count
61
+ Blocks[blocks_count] blocks
61
62
  }
62
63
 
63
64
  Node {
@@ -53,3 +53,11 @@ You may want to disable on-stack-replacement and inlining with
53
53
  easier to understand.
54
54
 
55
55
  You may need to use `--experimental-options`.
56
+
57
+ ## Getting basic blocks
58
+
59
+ To get the graph when scheduled, so that you can see basic blocks, use `-Dgraal.PrintGraphWithSchedule=true`. Truffle graphs beyond the initial stages have scheduling information by default.
60
+
61
+ ## Getting CFG files
62
+
63
+ To also get CFG files, add `-Dgraal.PrintBackendCFG=true`, or `--vm.Dgraal.PrintBackendCFG=true` for Truffle.
data/examples/Fib.java CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * % javac Fib.java
3
- * % java -XX:CompileOnly=::fib -Dgraal.Dump=:2 Fib 14
3
+ * % java -XX:CompileOnly=::fib -Dgraal.Dump=:2 -Dgraal.PrintGraphWithSchedule=true Fib 14
4
4
  */
5
5
 
6
6
  class Fib {
Binary file
data/examples/fib.js CHANGED
@@ -1,4 +1,4 @@
1
- // % node --experimental-options --engine.CompileOnly=fib --engine.Inlining=false --vm.Dgraal.Dump=Truffle:2 -f fib.js 14
1
+ // % node --experimental-options --engine.CompileOnly=fib --engine.Inlining=false --vm.Dgraal.Dump=Truffle:2 fib.js 14
2
2
 
3
3
  function fib(n) {
4
4
  if (n <= 1) {
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * % javac JavaExamples.java
3
- * % java -XX:-UseOnStackReplacement '-XX:CompileCommand=dontinline,*::*' -XX:+PrintCompilation -Dgraal.Dump=:3 JavaExamples
3
+ * % java -XX:-UseOnStackReplacement '-XX:CompileCommand=dontinline,*::*' -XX:+PrintCompilation -Dgraal.PrintBackendCFG=true -Dgraal.Dump=:3 JavaExamples
4
4
  */
5
5
 
6
6
  import java.lang.reflect.Field;
@@ -0,0 +1,20 @@
1
+ # ruby --experimental-options --engine.CompileOnly=clamp_low,clamp_high --vm.Dgraal.Dump=Truffle:2 --vm.Dgraal.PrintBackendCFG=true clamps.rb
2
+
3
+ def clamp_high(min, max, value)
4
+ [min, max, value].sort[1]
5
+ end
6
+
7
+ def clamp_low(min, max, value)
8
+ if value > max
9
+ max
10
+ elsif value < min
11
+ min
12
+ else
13
+ value
14
+ end
15
+ end
16
+
17
+ loop do
18
+ clamp_high(10, 90, rand(100))
19
+ clamp_low(10, 90, rand(100))
20
+ end
@@ -0,0 +1,15 @@
1
+ diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/phases/inlining/DefaultInliningPolicy.java b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/phases/inlining/DefaultInliningPolicy.java
2
+ index ffe01c1688f..d662a7096c4 100644
3
+ --- a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/phases/inlining/DefaultInliningPolicy.java
4
+ +++ b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/phases/inlining/DefaultInliningPolicy.java
5
+ @@ -114,6 +114,10 @@ final class DefaultInliningPolicy implements InliningPolicy {
6
+ final PriorityQueue<CallNode> inlineQueue = getQueue(tree, CallNode.State.Expanded);
7
+ CallNode candidate;
8
+ while ((candidate = inlineQueue.poll()) != null) {
9
+ + if (candidate.getName().startsWith("Object#opaque_") || candidate.getName().equals("Object#static_call") || candidate.getName().equals("ExampleObject#instance_call")) {
10
+ + continue;
11
+ + }
12
+ +
13
+ if (candidate.isTrivial()) {
14
+ candidate.inline();
15
+ continue;
@@ -0,0 +1,278 @@
1
+ # truffleruby_primitives: true
2
+
3
+ # We're using Graal with graal.patch, to disable some inlining.
4
+
5
+ # % ruby --jvm --experimental-options --engine.OSR=false --engine.MultiTier=false --engine.TraceCompilation --vm.Dgraal.Dump=Truffle:1 ruby_examples.rb
6
+
7
+ RANDOM = Random.new
8
+ EXCEPTION = Exception.new
9
+
10
+ def example_local_variables(x, y)
11
+ a = x + y
12
+ a * 2 + a
13
+ end
14
+
15
+ def example_local_variables_state(x, y)
16
+ a = x + y
17
+ opaque_call
18
+ a * 2 + a
19
+ end
20
+
21
+ def example_arith_operator(x, y)
22
+ x + y
23
+ end
24
+
25
+ def example_compare_operator(x, y)
26
+ x <= y
27
+ end
28
+
29
+ def example_phi(condition, x)
30
+ if condition
31
+ a = opaque_call_a
32
+ else
33
+ a = opaque_call_b
34
+ end
35
+ a + x
36
+ end
37
+
38
+ def example_simple_call(object, x)
39
+ object.instance_call(x)
40
+ end
41
+
42
+ def example_stamp(x)
43
+ x & 0x1234
44
+ end
45
+
46
+ def example_full_escape(x)
47
+ a = [x]
48
+ Primitive.blackhole a
49
+ a[0]
50
+ end
51
+
52
+ def example_no_escape(x)
53
+ a = [x]
54
+ a[0]
55
+ end
56
+
57
+ def example_partial_escape(condition, x)
58
+ a = [x]
59
+ if condition
60
+ Primitive.blackhole a
61
+ a[0]
62
+ else
63
+ a[0]
64
+ end
65
+ end
66
+
67
+ def example_if(condition, x, y)
68
+ if condition
69
+ Primitive.blackhole x
70
+ a = x
71
+ else
72
+ Primitive.blackhole y
73
+ a = y
74
+ end
75
+ a
76
+ end
77
+
78
+ def example_if_never_taken(condition, x, y)
79
+ if condition
80
+ Primitive.blackhole x
81
+ a = x
82
+ else
83
+ Primitive.blackhole y
84
+ a = y
85
+ end
86
+ a
87
+ end
88
+
89
+ def example_int_switch(value, x, y, z)
90
+ case value
91
+ when 0
92
+ Primitive.blackhole x
93
+ a = x
94
+ when 1
95
+ Primitive.blackhole y
96
+ a = y
97
+ else
98
+ Primitive.blackhole z
99
+ a = z
100
+ end
101
+ a
102
+ end
103
+
104
+ def example_string_switch(value, x, y, z)
105
+ case value
106
+ when 'foo'
107
+ Primitive.blackhole x
108
+ a = x
109
+ when 'bar'
110
+ Primitive.blackhole y
111
+ a = y
112
+ else
113
+ Primitive.blackhole z
114
+ a = z
115
+ end
116
+ a
117
+ end
118
+
119
+ def example_while(count)
120
+ a = count
121
+ while a > 0
122
+ Primitive.blackhole a
123
+ a -= 1
124
+ end
125
+ count
126
+ end
127
+
128
+ def example_for(count)
129
+ count.times do |a|
130
+ Primitive.blackhole a
131
+ end
132
+ end
133
+
134
+ def example_nested_while(count)
135
+ a = count
136
+ while (a > 0)
137
+ y = count
138
+ while (y > 0)
139
+ Primitive.blackhole a
140
+ y -= 1
141
+ end
142
+ a -= 1
143
+ end
144
+ count
145
+ end
146
+
147
+ def example_while_break(count)
148
+ a = count
149
+ while a > 0
150
+ if a == 4
151
+ break
152
+ end
153
+ Primitive.blackhole a
154
+ a -= 1
155
+ end
156
+ count
157
+ end
158
+
159
+ def example_raise
160
+ raise EXCEPTION
161
+ end
162
+
163
+ def example_rescue
164
+ begin
165
+ opaque_raise
166
+ rescue Exception => e
167
+ Primitive.blackhole e
168
+ end
169
+ end
170
+
171
+ def example_raise_rescue
172
+ begin
173
+ raise EXCEPTION
174
+ rescue Exception => e
175
+ Primitive.blackhole e
176
+ end
177
+ end
178
+
179
+ def example_object_allocation(x)
180
+ ExampleObject.new(x)
181
+ end
182
+
183
+ def example_array_allocation(x, y)
184
+ [x, y]
185
+ end
186
+
187
+ def example_field_write(object, x)
188
+ object.x = x
189
+ end
190
+
191
+ def example_field_read(object)
192
+ object.x
193
+ end
194
+
195
+ def example_array_write(array, n, x)
196
+ array[n] = x
197
+ end
198
+
199
+ def example_array_read(array, n)
200
+ array[n]
201
+ end
202
+
203
+ def example_instance_of(x)
204
+ x.is_a?(ExampleObject)
205
+ end
206
+
207
+ # no inline
208
+ def opaque_call
209
+ RANDOM.rand(1000)
210
+ end
211
+
212
+ # no inline
213
+ def opaque_call_a
214
+ opaque_call
215
+ end
216
+
217
+ # no inline
218
+ def opaque_call_b
219
+ opaque_call
220
+ end
221
+
222
+ # no inline
223
+ def opaque_raise
224
+ raise EXCEPTION
225
+ end
226
+
227
+ # no inline
228
+ def static_call(x)
229
+ x
230
+ end
231
+
232
+ class ExampleObject
233
+ attr_accessor :x
234
+
235
+ def initialize(x)
236
+ @x = x
237
+ end
238
+
239
+ # no inline
240
+ def instance_call(y)
241
+ @x + y
242
+ end
243
+ end
244
+
245
+ loop do
246
+ example_local_variables RANDOM.rand(1000), RANDOM.rand(1000)
247
+ example_local_variables_state RANDOM.rand(1000), RANDOM.rand(1000)
248
+ example_arith_operator RANDOM.rand(1000), RANDOM.rand(1000)
249
+ example_compare_operator RANDOM.rand(1000), RANDOM.rand(1000)
250
+ example_phi [true, false].sample, RANDOM.rand(1000)
251
+ example_simple_call ExampleObject.new(RANDOM.rand(1000)), RANDOM.rand(1000)
252
+ example_stamp RANDOM.rand(1000)
253
+ example_full_escape RANDOM.rand(1000)
254
+ example_no_escape RANDOM.rand(1000)
255
+ example_partial_escape [true, false].sample, RANDOM.rand(1000)
256
+ example_if [true, false].sample, RANDOM.rand(1000), RANDOM.rand(1000)
257
+ example_if_never_taken false, RANDOM.rand(1000), RANDOM.rand(1000)
258
+ example_int_switch RANDOM.rand(3), RANDOM.rand(1000), RANDOM.rand(1000), RANDOM.rand(1000)
259
+ example_string_switch ['foo', 'bar', 'baz'].sample, RANDOM.rand(1000), RANDOM.rand(1000), RANDOM.rand(1000)
260
+ example_while RANDOM.rand(10)
261
+ example_for RANDOM.rand(10)
262
+ example_nested_while RANDOM.rand(10)
263
+ example_while_break RANDOM.rand(10)
264
+ begin
265
+ example_raise
266
+ rescue Exception => e
267
+ #
268
+ end
269
+ example_rescue
270
+ example_raise_rescue
271
+ example_object_allocation RANDOM.rand(1000)
272
+ example_array_allocation RANDOM.rand(1000), RANDOM.rand(1000)
273
+ example_field_write ExampleObject.new(RANDOM.rand(1000)), RANDOM.rand(1000)
274
+ example_field_read ExampleObject.new(RANDOM.rand(1000))
275
+ example_array_write [RANDOM.rand(1000), RANDOM.rand(1000), RANDOM.rand(1000)], RANDOM.rand(3), RANDOM.rand(1000)
276
+ example_array_read [RANDOM.rand(1000), RANDOM.rand(1000), RANDOM.rand(1000)], RANDOM.rand(3)
277
+ example_instance_of [Object.new, ExampleObject.new(0)].sample
278
+ end
data/lib/seafoam.rb CHANGED
@@ -1,13 +1,17 @@
1
1
  require 'seafoam/version'
2
2
  require 'seafoam/binary/io_binary_reader'
3
3
  require 'seafoam/bgv/bgv_parser'
4
+ require 'seafoam/cfg/cfg_parser'
5
+ require 'seafoam/cfg/disassembler'
4
6
  require 'seafoam/colors'
5
7
  require 'seafoam/graph'
6
- require 'seafoam/graal'
8
+ require 'seafoam/graal/source'
7
9
  require 'seafoam/annotators'
8
10
  require 'seafoam/annotators/graal'
9
11
  require 'seafoam/annotators/fallback'
10
12
  require 'seafoam/spotlight'
13
+ require 'seafoam/isabelle_writer'
14
+ require 'seafoam/json_writer'
11
15
  require 'seafoam/graphviz_writer'
12
16
  require 'seafoam/config'
13
17
  require 'seafoam/commands'
@@ -357,7 +357,7 @@ module Seafoam
357
357
  TRIGGERS = %w[
358
358
  HostedGraphBuilderPhase
359
359
  GraalCompiler
360
- TruffleCompilerThread
360
+ TruffleCompiler
361
361
  ]
362
362
 
363
363
  # Simple input node classes that may be inlined.
@@ -127,13 +127,21 @@ module Seafoam
127
127
  end
128
128
  end
129
129
  end
130
- skip_blocks
130
+
131
+ # Read block information.
132
+ @reader.read_sint32.times do
133
+ block_id = @reader.read_sint32
134
+ block_nodes = @reader.read_sint32.times.map { @reader.read_sint32 }
135
+ # Followers aren't used but could be.
136
+ @reader.read_sint32.times.map { @reader.read_sint32 }
137
+ graph.create_block block_id, block_nodes
138
+ end
131
139
  graph
132
140
  end
133
141
 
134
142
  # Skip over a graph, having read or skipped its headers.
135
143
  def skip_graph
136
- # Already read BEGIN_GRAPH, id, format, args, and props
144
+ # Already read BEGIN_GRAPH, id, format, args, and props.
137
145
  @reader.read_sint32.times do
138
146
  @reader.skip_int32
139
147
  node_class = read_pool_object
@@ -0,0 +1,93 @@
1
+ require 'stringio'
2
+ require 'zlib'
3
+
4
+ module Seafoam
5
+ module CFG
6
+ Code = Struct.new(:arch, :arch_width, :base, :code)
7
+ Comment = Struct.new(:offset, :comment)
8
+ NMethod = Struct.new(:code, :comments)
9
+
10
+ # A parser for CFG files.
11
+ class CFGParser
12
+ def initialize(out, file)
13
+ @out = out
14
+ data = File.read(file, encoding: Encoding::ASCII_8BIT)
15
+ if data[0..1].bytes == [0x1f, 0x8b]
16
+ data = Zlib.gunzip(data)
17
+ end
18
+ @reader = StringIO.new(data)
19
+ @state = :any
20
+ @cfg_name = nil
21
+ end
22
+
23
+ def skip_over_cfg(name)
24
+ loop do
25
+ line = @reader.readline("\n")
26
+ case line
27
+ when "begin_cfg\n"
28
+ @state = :cfg
29
+ @cfg_name = nil
30
+ when / name "(.*)"\n/
31
+ if @state == :cfg
32
+ @cfg_name = Regexp.last_match(1)
33
+ end
34
+ when "end_cfg\n"
35
+ raise unless @state == :cfg
36
+
37
+ @state = :any
38
+ break if @cfg_name == name
39
+ else
40
+ next
41
+ end
42
+ end
43
+ end
44
+
45
+ def read_nmethod
46
+ raise unless @state == :any
47
+
48
+ arch = nil
49
+ arch_width = nil
50
+ code = nil
51
+ comments = []
52
+ raise unless @reader.readline == "begin_nmethod\n"
53
+
54
+ loop do
55
+ line = @reader.readline("\n")
56
+ case line
57
+ when / Platform (.*) (.*) <\|\|@\n/
58
+ arch = Regexp.last_match(1)
59
+ arch_width = Regexp.last_match(2)
60
+ when / HexCode (.*) (.*) <\|\|@\n/
61
+ base = Regexp.last_match(1).to_i(16)
62
+ code = [Regexp.last_match(2)].pack('H*')
63
+ raise if arch.nil? || arch_width.nil?
64
+
65
+ code = Code.new(arch, arch_width, base, code)
66
+ when / Comment (\d*) (.*) <\|\|@\n/
67
+ offset = Regexp.last_match(1).to_i
68
+ comment = Regexp.last_match(2)
69
+ comments.push Comment.new(offset, comment)
70
+ when " <<<HexCodeFile\n"
71
+ next
72
+ when " HexCodeFile>>> <|@\n"
73
+ next
74
+ when "end_nmethod\n"
75
+ break
76
+ when / (.*) <\|\|@\n/
77
+ offset = -1
78
+ comment = Regexp.last_match(1)
79
+ comments.push Comment.new(offset, comment)
80
+ when / (.*)\n/
81
+ offset = -1
82
+ comment = Regexp.last_match(1)
83
+ comments.push Comment.new(offset, comment)
84
+ else
85
+ # In case anything was missed
86
+ raise 'There is currently no case for this line. Please open an issue so it can be addressed.'
87
+ end
88
+ end
89
+ NMethod.new(code, comments)
90
+ end
91
+ end
92
+ end
93
+ end