Module: Trepanning::Method

Defined in:
app/method.rb

Class Method Summary collapse

Class Method Details

.find_method_with_line(cm, line) ⇒ Object

Returns a CompiledMethod for the specified line. We search the current method meth and then up the parent scope. If we hit the top and we can’t find line that way, then we reverse the search from the top and search down. This will add all siblings of ancestors of meth.



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'app/method.rb', line 78

def find_method_with_line(cm, line)
  unless cm.kind_of?(Rubinius::CompiledMethod)
    return nil
  end

  lines = lines_of_method(cm)
  return cm if lines.member?(line)
  scope = cm.scope
  return nil unless scope and scope.current_script
  cm  = scope.current_script.compiled_code
  lines = lines_of_method(cm)
  until lines.member?(line) do
    child = scope
    scope = scope.parent
    unless scope
      # child is the top-most scope. Search down from here.
      cm = child.current_script.compiled_code
      pair = locate_line(line, cm)
      ## pair = cm.locate_line(line)
      return pair ? pair[0] : nil
    end
    cm = scope.current_script.compiled_code
    lines = lines_of_method(cm)
  end
  return cm
end

.lines_of_method(cm) ⇒ Object



58
59
60
61
62
63
64
# File 'app/method.rb', line 58

def lines_of_method(cm)
  lines = []
  cm.lines.each_with_index do |l, i|
    lines << l if (i&1 == 1)
  end
  return lines
end

.locate_line(line, cm = self) ⇒ (Rubinius::CompiledMethod, Fixnum), NilClass

FIXME: Try using Routine in Rubinius now.

Locates the CompiledMethod and instruction address (IP) of the first instruction on the specified line. This method recursively examines child compiled methods until an exact match for the searched line is found. It returns both the matching CompiledMethod and the IP of the first instruction on the requested line, or nil if no match for the specified line is found.

Returns:

  • ((Rubinius::CompiledMethod, Fixnum), NilClass)

    returns nil if nothing is found, else an array of size 2 containing the method the line was found in and the IP pointing there.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'app/method.rb', line 41

def locate_line(line, cm=self)
  ## p [cm, lines_of_method(cm)]
  ip = locate_line_in_cm(line, cm)
  return cm, ip if ip

  # Didn't find line in this CM, so check if a contained
  # CM encompasses the line searched for
  cm.child_methods.each do |child|
    if res = locate_line(line, child)
      return res
    end
  end

  # No child method is a match - fail
  return nil
end

.locate_line_in_cm(line, cm = self) ⇒ Fixnum, NilClass

FIXME: until the next two routines find their way back into Rubinius::CompiledMethod…

Locates the instruction address (IP) of the first instruction on the specified line if is in CompiledMethod cm only, or nil if no match for the specified line is found.

Returns:

  • (Fixnum, NilClass)

    returns nil if nothing is found, else the first IP for the line



15
16
17
18
19
20
21
22
23
24
25
26
# File 'app/method.rb', line 15

def locate_line_in_cm(line, cm=self)
  cm.lines.each_with_index do |l, i|
    next unless (i&1 == 1)
    if (l ==  line)
      # Found target line - return first IP
      return cm.lines[i-1]
    elsif l > line
      return nil
    end
  end
  return nil
end

.top_scope(cm) ⇒ Object



105
106
107
108
109
110
111
112
113
114
# File 'app/method.rb', line 105

def top_scope(cm)
  scope = cm.scope
  return unless scope
  while true do
    scope = scope.parent
    break unless scope && scope.current_script
    cm = scope.current_script.compiled_code
  end
  cm
end

.valid_ip?(cm, ip) ⇒ Boolean

Return true if ip is the start of some instruction in meth. FIXME: be more stringent.

Returns:

  • (Boolean)


68
69
70
71
# File 'app/method.rb', line 68

def valid_ip?(cm, ip)
  size = cm.lines.size
  ip >= 0 && ip < cm.lines[size-1]
end