Skip to content

Commit

Permalink
Support b_call/b_return
Browse files Browse the repository at this point in the history
Fixed a bug that caused a discrepancy between stack and caller when block is called.
  • Loading branch information
alpaca-tc committed May 23, 2024
1 parent 09ac9da commit 57d772d
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 6 deletions.
6 changes: 1 addition & 5 deletions lib/diver_down/trace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,12 @@ module Trace
require 'diver_down/trace/redefine_ruby_methods'
require 'diver_down/trace/ignored_method_ids'

@trace_events = %i[
call c_call return c_return
]

# Trace only Ruby-implemented methods because tracing C-implemented methods is very slow
# Override Ruby only with the minimal set of methods needed to trace dependencies.
#
# @return [void]
def self.trace_only_ruby_world!(map = DiverDown::Trace::RedefineRubyMethods::DEFAULT_METHODS)
DiverDown::Trace::Tracer.trace_events = %i[call return]
DiverDown::Trace::Tracer.trace_events = DiverDown::Trace::Tracer::DEFAULT_TRACE_EVENTS - %i[c_call c_return]
DiverDown::Trace::RedefineRubyMethods.redefine_c_methods(map)
end
end
Expand Down
4 changes: 4 additions & 0 deletions lib/diver_down/trace/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ def build_trace_point
next if TracePoint == tp.defined_class

case tp.event
when :b_call
call_stack.push
when :b_return
call_stack.pop
when :call, :c_call
# puts "#{tp.method_id} #{tp.path}:#{tp.lineno}"
if call_stack.ignored?
Expand Down
11 changes: 10 additions & 1 deletion lib/diver_down/trace/tracer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@
module DiverDown
module Trace
class Tracer
DEFAULT_TRACE_EVENTS = %i[
call
return
c_call
c_return
b_call
b_return
].freeze

# @return [Array<Symbol>]
def self.trace_events
@trace_events || %i[call c_call return c_return]
@trace_events || DEFAULT_TRACE_EVENTS
end

# @param events [Array<Symbol>]
Expand Down
87 changes: 87 additions & 0 deletions spec/diver_down/trace/tracer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,93 @@ def trace_fixture(path, module_set: {}, caller_paths: nil, ignored_method_ids: [
))
end

it 'traces tracer_with_block.rb' do
wrapper = Class.new do
def self.wrap
yield
end
end
stub_const('Wrapper', wrapper)

definition = wrapper.wrap do
trace_fixture(
'tracer_with_block.rb',
caller_paths: [
fixture_path('tracer_with_block.rb'),
],
module_set: {
modules: [
'Wrapper',
'AntipollutionModule::A',
'AntipollutionModule::B',
'AntipollutionModule::C',
'AntipollutionModule::D',
],
}
)
end

expect(definition.to_h).to match(fill_default(
title: 'title',
sources: [
{
source_name: 'AntipollutionModule::A',
dependencies: [
{
source_name: 'AntipollutionModule::B',
method_ids: [
{
name: 'call_c',
context: 'class',
paths: [
match(/tracer_with_block\.rb:\d+/),
],
},
],
},
],
},
{
source_name: 'AntipollutionModule::B',
dependencies: [
{
source_name: 'AntipollutionModule::C',
method_ids: [
{
name: 'call_d',
context: 'class',
paths: [
match(/tracer_with_block\.rb:\d+/),
],
},
],
},
],
},
{
source_name: 'AntipollutionModule::C',
dependencies: [
{
source_name: 'AntipollutionModule::D',
method_ids: [
{
name: 'call_name',
context: 'class',
paths: [
match(/tracer_with_block\.rb:\d+/),
],
},
],
},
],
},
{
source_name: 'AntipollutionModule::D',
},
]
))
end

it 'traces tracer_subclass.rb' do
definition = trace_fixture(
'tracer_subclass.rb',
Expand Down
15 changes: 15 additions & 0 deletions spec/fixtures/tracer_with_block.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
load "#{__dir__}/tracer_with_block/b.rb"
load "#{__dir__}/tracer_with_block/c.rb"
load "#{__dir__}/tracer_with_block/d.rb"

def run
A.call_b
end

class A
def self.call_b
yield_self do
B.call_c
end
end
end
7 changes: 7 additions & 0 deletions spec/fixtures/tracer_with_block/b.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class B
def self.call_c
yield_self do
C.call_d
end
end
end
11 changes: 11 additions & 0 deletions spec/fixtures/tracer_with_block/c.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class C
def self.call_d
yield_self do
yield_self do
yield_self do
D.call_name
end
end
end
end
end
5 changes: 5 additions & 0 deletions spec/fixtures/tracer_with_block/d.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class D
def self.call_name
'name'
end
end

0 comments on commit 57d772d

Please sign in to comment.