Skip to content

Commit 0251374

Browse files
committed
fix(tracer): align type handling
1 parent 7891e89 commit 0251374

File tree

3 files changed

+412
-27
lines changed

3 files changed

+412
-27
lines changed

gems/native-tracer/ext/native_tracer/src/lib.rs

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ struct Recorder {
8484
inst_meth_id: ID,
8585
parameters_id: ID,
8686
class_id: ID,
87-
struct_types: HashMap<String, runtime_tracing::TypeId>,
87+
struct_type_versions: HashMap<String, usize>,
8888
}
8989

9090
fn value_type_id(val: &ValueRecord) -> runtime_tracing::TypeId {
@@ -119,26 +119,26 @@ unsafe fn struct_value(
119119
vals.push(to_value(recorder, *v, depth - 1, to_s_id));
120120
}
121121

122-
let type_id = if let Some(id) = recorder.struct_types.get(class_name) {
123-
*id
124-
} else {
125-
let field_types: Vec<FieldTypeRecord> = field_names
126-
.iter()
127-
.zip(&vals)
128-
.map(|(n, v)| FieldTypeRecord {
129-
name: (*n).to_string(),
130-
type_id: value_type_id(v),
131-
})
132-
.collect();
133-
let typ = TypeRecord {
134-
kind: TypeKind::Struct,
135-
lang_type: class_name.to_string(),
136-
specific_info: TypeSpecificInfo::Struct { fields: field_types },
137-
};
138-
let id = recorder.tracer.ensure_raw_type_id(typ);
139-
recorder.struct_types.insert(class_name.to_string(), id);
140-
id
122+
let version_entry = recorder
123+
.struct_type_versions
124+
.entry(class_name.to_string())
125+
.or_insert(0);
126+
let name_version = format!("{} (#{})", class_name, *version_entry);
127+
*version_entry += 1;
128+
let field_types: Vec<FieldTypeRecord> = field_names
129+
.iter()
130+
.zip(&vals)
131+
.map(|(n, v)| FieldTypeRecord {
132+
name: (*n).to_string(),
133+
type_id: value_type_id(v),
134+
})
135+
.collect();
136+
let typ = TypeRecord {
137+
kind: TypeKind::Struct,
138+
lang_type: name_version,
139+
specific_info: TypeSpecificInfo::Struct { fields: field_types },
141140
};
141+
let type_id = recorder.tracer.ensure_raw_type_id(typ);
142142

143143
ValueRecord::Struct {
144144
field_values: vals,
@@ -197,7 +197,7 @@ unsafe extern "C" fn ruby_recorder_alloc(klass: VALUE) -> VALUE {
197197
inst_meth_id,
198198
parameters_id,
199199
class_id,
200-
struct_types: HashMap::new(),
200+
struct_type_versions: HashMap::new(),
201201
});
202202
let ty = std::ptr::addr_of!(RECORDER_TYPE) as *const rb_data_type_t;
203203
rb_data_typed_object_wrap(klass, Box::into_raw(recorder) as *mut c_void, ty)
@@ -577,7 +577,13 @@ unsafe extern "C" fn event_hook_raw(data: VALUE, arg: *mut rb_trace_arg_t) {
577577
String::from_utf8_lossy(std::slice::from_raw_parts(ptr as *const u8, len)).to_string()
578578
};
579579
let line = rb_num2long(line_val) as i64;
580-
if path.contains("native_trace.rb") {
580+
if path.contains("native_trace.rb")
581+
|| path.contains("lib/ruby")
582+
|| path.contains("recorder.rb")
583+
|| path.contains("trace.rb")
584+
|| path.contains("gems/")
585+
|| path.starts_with("<internal:")
586+
{
581587
return;
582588
}
583589

@@ -594,9 +600,9 @@ unsafe extern "C" fn event_hook_raw(data: VALUE, arg: *mut rb_trace_arg_t) {
594600
let mid_sym = rb_tracearg_callee_id(arg);
595601
let mid = rb_sym2id(mid_sym);
596602
let defined_class = rb_funcall(self_val, recorder.class_id, 0);
597-
let mut args = Vec::new();
598603
if !NIL_P(binding) {
599-
args = record_parameters(recorder, binding, defined_class, mid, true);
604+
// ensure parameter types are registered before self
605+
let _ = record_parameters(recorder, binding, defined_class, mid, false);
600606
}
601607
let class_name = cstr_to_string(rb_obj_classname(self_val)).unwrap_or_else(|| "Object".to_string());
602608
let text = value_to_string_safe(self_val, recorder.to_s_id).unwrap_or_default();
@@ -606,6 +612,12 @@ unsafe extern "C" fn event_hook_raw(data: VALUE, arg: *mut rb_trace_arg_t) {
606612
.tracer
607613
.register_variable_with_full_value("self", self_rec.clone());
608614

615+
let mut args = if NIL_P(binding) {
616+
Vec::new()
617+
} else {
618+
record_parameters(recorder, binding, defined_class, mid, true)
619+
};
620+
609621
args.insert(0, recorder.tracer.arg("self", self_rec));
610622
recorder.tracer.register_step(Path::new(&path), Line(line));
611623
let name_c = rb_id2name(mid);

gems/pure-ruby-tracer/lib/recorder.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def to_data_for_json
4646
end
4747

4848

49-
ValueRecord = Struct.new(:kind, :type_id, :i, :b, :text, :r, :msg, :elements, :is_slice, :field_values, keyword_init: true) do
49+
ValueRecord = Struct.new(:kind, :type_id, :i, :f, :b, :text, :r, :msg, :elements, :is_slice, :field_values, keyword_init: true) do
5050
def to_data_for_json
5151
res = to_h.compact
5252
if !res[:elements].nil?
@@ -402,7 +402,7 @@ def to_value(v, depth=10)
402402
end
403403
when Range
404404
struct_value('Range', ['begin', 'end'], [v.begin, v.end], depth)
405-
when defined?(Set) && v.is_a?(Set)
405+
when ->(o) { defined?(Set) && o.is_a?(Set) }
406406
if v.size > MAX_COUNT
407407
NOT_SUPPORTED_VALUE
408408
else
@@ -414,7 +414,7 @@ def to_value(v, depth=10)
414414
struct_value('Regexp', ['source', 'options'], [v.source, v.options], depth)
415415
when Struct
416416
struct_value(v.class.name, v.members.map(&:to_s), v.values, depth)
417-
when defined?(OpenStruct) && v.is_a?(OpenStruct)
417+
when ->(o) { defined?(OpenStruct) && o.is_a?(OpenStruct) }
418418
h = v.to_h
419419
pairs = h.map do |k, val|
420420
struct_value('Pair', ['k', 'v'], [k, val], depth)

0 commit comments

Comments
 (0)