Class: Pf2::Reporter::StackWeaver

Inherits:
Object
  • Object
show all
Defined in:
lib/pf2/reporter/stack_weaver.rb

Instance Method Summary collapse

Constructor Details

#initialize(profile) ⇒ StackWeaver

Returns a new instance of StackWeaver.



6
7
8
# File 'lib/pf2/reporter/stack_weaver.rb', line 6

def initialize(profile)
  @profile = profile
end

Instance Method Details

#should_switch_to_native?(location_index, native_stack_remainder) ⇒ Boolean

Parameters:

  • location_index (Integer)
  • native_stack_remainder (Array<Integer>)

Returns:

  • (Boolean)


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/pf2/reporter/stack_weaver.rb', line 49

def should_switch_to_native?(location_index, native_stack_remainder)
  location = @profile[:locations][location_index]
  function = @profile[:functions][location[:function_index]]
  raise if function[:implementation] != :ruby # assert

  # Is the current Ruby function a cfunc?
  return false if function[:start_address] == nil

  # Does a corresponding native function exist in the remainder of the native stack?
  loop do
    break if native_stack_remainder.size == 0
    n_location_index = native_stack_remainder.pop
    n_location = @profile[:locations][n_location_index]
    n_function = @profile[:functions][n_location[:function_index]]

    return true if function[:start_address] == n_function[:start_address]
  end

  false
end

#should_switch_to_ruby?(location_index) ⇒ Boolean

Returns:

  • (Boolean)


70
71
72
73
74
75
76
77
78
# File 'lib/pf2/reporter/stack_weaver.rb', line 70

def should_switch_to_ruby?(location_index)
  location = @profile[:locations][location_index]
  function = @profile[:functions][location[:function_index]]
  raise if function[:implementation] != :native # assert

  # If the next function is a vm_exec_core() (= VM_EXEC in vm_exec.h),
  # we switch to the Ruby stack.
  function[:name] == 'vm_exec_core'
end

#weave(ruby_stack, native_stack) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/pf2/reporter/stack_weaver.rb', line 10

def weave(ruby_stack, native_stack)
  ruby_stack = ruby_stack.dup
  native_stack = native_stack.dup

  weaved_stack = []

  current_stack = :native
  loop do
    break if ruby_stack.size == 0 && native_stack.size == 0
    case current_stack
    when :ruby
      if ruby_stack.size == 0 # We've reached the end of the Ruby stack
        current_stack = :native
        next
      end

      location_index = ruby_stack.pop
      weaved_stack.unshift(location_index)

      current_stack = :native if should_switch_to_native?(location_index, native_stack.dup)

    when :native
      if native_stack.size == 0 # We've reached the end of the native stack
        current_stack = :ruby
        next
      end

      location_index = native_stack.pop
      weaved_stack.unshift(location_index)

      current_stack = :ruby if should_switch_to_ruby?(location_index)
    end
  end

  weaved_stack
end