@@ -63,6 +63,12 @@ extern "C" {
6363struct Recorder {
6464 tracer : Tracer ,
6565 active : bool ,
66+ to_s_id : ID ,
67+ locals_id : ID ,
68+ local_get_id : ID ,
69+ inst_meth_id : ID ,
70+ parameters_id : ID ,
71+ class_id : ID ,
6672}
6773
6874unsafe extern "C" fn recorder_free ( ptr : * mut c_void ) {
@@ -101,7 +107,22 @@ unsafe extern "C" fn ruby_recorder_alloc(klass: VALUE) -> VALUE {
101107 let path = Path :: new ( "" ) ;
102108 let func_id = tracer. ensure_function_id ( "<top-level>" , path, Line ( 1 ) ) ;
103109 tracer. events . push ( TraceLowLevelEvent :: Call ( CallRecord { function_id : func_id, args : vec ! [ ] } ) ) ;
104- let recorder = Box :: new ( Recorder { tracer, active : false } ) ;
110+ let to_s_id = rb_intern ( b"to_s\0 " . as_ptr ( ) as * const c_char ) ;
111+ let locals_id = rb_intern ( b"local_variables\0 " . as_ptr ( ) as * const c_char ) ;
112+ let local_get_id = rb_intern ( b"local_variable_get\0 " . as_ptr ( ) as * const c_char ) ;
113+ let inst_meth_id = rb_intern ( b"instance_method\0 " . as_ptr ( ) as * const c_char ) ;
114+ let parameters_id = rb_intern ( b"parameters\0 " . as_ptr ( ) as * const c_char ) ;
115+ let class_id = rb_intern ( b"class\0 " . as_ptr ( ) as * const c_char ) ;
116+ let recorder = Box :: new ( Recorder {
117+ tracer,
118+ active : false ,
119+ to_s_id,
120+ locals_id,
121+ local_get_id,
122+ inst_meth_id,
123+ parameters_id,
124+ class_id,
125+ } ) ;
105126 let ty = std:: ptr:: addr_of!( RECORDER_TYPE ) as * const rb_data_type_t ;
106127 rb_data_typed_object_wrap ( klass, Box :: into_raw ( recorder) as * mut c_void , ty)
107128}
@@ -151,22 +172,21 @@ unsafe fn cstr_to_string(ptr: *const c_char) -> Option<String> {
151172 CStr :: from_ptr ( ptr) . to_str ( ) . ok ( ) . map ( |s| s. to_string ( ) )
152173}
153174
154- unsafe fn value_to_string ( val : VALUE ) -> Option < String > {
175+ unsafe fn value_to_string ( val : VALUE , to_s_id : ID ) -> Option < String > {
155176 if RB_TYPE_P ( val, rb_sys:: ruby_value_type:: RUBY_T_STRING ) {
156177 let ptr = RSTRING_PTR ( val) ;
157178 let len = RSTRING_LEN ( val) as usize ;
158179 let slice = std:: slice:: from_raw_parts ( ptr as * const u8 , len) ;
159180 return Some ( String :: from_utf8_lossy ( slice) . to_string ( ) ) ;
160181 }
161- let to_s_id = rb_intern ( b"to_s\0 " . as_ptr ( ) as * const c_char ) ;
162182 let str_val = rb_funcall ( val, to_s_id, 0 ) ;
163183 let ptr = RSTRING_PTR ( str_val) ;
164184 let len = RSTRING_LEN ( str_val) as usize ;
165185 let slice = std:: slice:: from_raw_parts ( ptr as * const u8 , len) ;
166186 Some ( String :: from_utf8_lossy ( slice) . to_string ( ) )
167187}
168188
169- unsafe fn to_value ( tracer : & mut Tracer , val : VALUE , depth : usize ) -> ValueRecord {
189+ unsafe fn to_value ( tracer : & mut Tracer , val : VALUE , depth : usize , to_s_id : ID ) -> ValueRecord {
170190 if depth == 0 {
171191 let type_id = tracer. ensure_type_id ( TypeKind :: Error , "No type" ) ;
172192 return ValueRecord :: None { type_id } ;
@@ -203,45 +223,40 @@ unsafe fn to_value(tracer: &mut Tracer, val: VALUE, depth: usize) -> ValueRecord
203223 let ptr = RARRAY_CONST_PTR ( val) ;
204224 for i in 0 ..len {
205225 let elem = * ptr. add ( i) ;
206- elements. push ( to_value ( tracer, elem, depth - 1 ) ) ;
226+ elements. push ( to_value ( tracer, elem, depth - 1 , to_s_id ) ) ;
207227 }
208228 let type_id = tracer. ensure_type_id ( TypeKind :: Seq , "Array" ) ;
209229 return ValueRecord :: Sequence { elements, is_slice : false , type_id } ;
210230 }
211231 let class_name = cstr_to_string ( rb_obj_classname ( val) ) . unwrap_or_else ( || "Object" . to_string ( ) ) ;
212- let text = value_to_string ( val) . unwrap_or_default ( ) ;
232+ let text = value_to_string ( val, to_s_id ) . unwrap_or_default ( ) ;
213233 let type_id = tracer. ensure_type_id ( TypeKind :: Raw , & class_name) ;
214234 ValueRecord :: Raw { r : text, type_id }
215235}
216236
217- unsafe fn record_variables ( tracer : & mut Tracer , binding : VALUE ) -> Vec < FullValueRecord > {
237+ unsafe fn record_variables ( recorder : & mut Recorder , binding : VALUE ) -> Vec < FullValueRecord > {
218238 let mut result = Vec :: new ( ) ;
219- let locals_id = rb_intern ( b"local_variables\0 " . as_ptr ( ) as * const c_char ) ;
220- let get_id = rb_intern ( b"local_variable_get\0 " . as_ptr ( ) as * const c_char ) ;
221- let vars = rb_funcall ( binding, locals_id, 0 ) ;
239+ let vars = rb_funcall ( binding, recorder. locals_id , 0 ) ;
222240 let len = RARRAY_LEN ( vars) as usize ;
223241 let ptr = RARRAY_CONST_PTR ( vars) ;
224242 for i in 0 ..len {
225243 let sym = * ptr. add ( i) ;
226244 let id = rb_sym2id ( sym) ;
227245 let name = CStr :: from_ptr ( rb_id2name ( id) ) . to_str ( ) . unwrap_or ( "" ) ;
228- let value = rb_funcall ( binding, get_id , 1 , sym) ;
229- let val_rec = to_value ( tracer, value, 10 ) ;
230- tracer. register_variable_with_full_value ( name, val_rec. clone ( ) ) ;
231- let var_id = tracer. ensure_variable_id ( name) ;
246+ let value = rb_funcall ( binding, recorder . local_get_id , 1 , sym) ;
247+ let val_rec = to_value ( & mut recorder . tracer , value, 10 , recorder . to_s_id ) ;
248+ recorder . tracer . register_variable_with_full_value ( name, val_rec. clone ( ) ) ;
249+ let var_id = recorder . tracer . ensure_variable_id ( name) ;
232250 result. push ( FullValueRecord { variable_id : var_id, value : val_rec } ) ;
233251 }
234252 result
235253}
236254
237- unsafe fn record_parameters ( tracer : & mut Tracer , binding : VALUE , defined_class : VALUE , mid : ID , register : bool ) -> Vec < FullValueRecord > {
255+ unsafe fn record_parameters ( recorder : & mut Recorder , binding : VALUE , defined_class : VALUE , mid : ID , register : bool ) -> Vec < FullValueRecord > {
238256 let mut result = Vec :: new ( ) ;
239- let inst_meth_id = rb_intern ( b"instance_method\0 " . as_ptr ( ) as * const c_char ) ;
240- let parameters_id = rb_intern ( b"parameters\0 " . as_ptr ( ) as * const c_char ) ;
241- let local_get_id = rb_intern ( b"local_variable_get\0 " . as_ptr ( ) as * const c_char ) ;
242257 let method_sym = rb_id2sym ( mid) ;
243- let method_obj = rb_funcall ( defined_class, inst_meth_id, 1 , method_sym) ;
244- let params_ary = rb_funcall ( method_obj, parameters_id, 0 ) ;
258+ let method_obj = rb_funcall ( defined_class, recorder . inst_meth_id , 1 , method_sym) ;
259+ let params_ary = rb_funcall ( method_obj, recorder . parameters_id , 0 ) ;
245260 let params_len = RARRAY_LEN ( params_ary) as usize ;
246261 let params_ptr = RARRAY_CONST_PTR ( params_ary) ;
247262 for i in 0 ..params_len {
@@ -260,11 +275,11 @@ unsafe fn record_parameters(tracer: &mut Tracer, binding: VALUE, defined_class:
260275 continue ;
261276 }
262277 let name = CStr :: from_ptr ( name_c) . to_str ( ) . unwrap_or ( "" ) ;
263- let value = rb_funcall ( binding, local_get_id, 1 , name_sym) ;
264- let val_rec = to_value ( tracer, value, 10 ) ;
278+ let value = rb_funcall ( binding, recorder . local_get_id , 1 , name_sym) ;
279+ let val_rec = to_value ( & mut recorder . tracer , value, 10 , recorder . to_s_id ) ;
265280 if register {
266- tracer. register_variable_with_full_value ( name, val_rec. clone ( ) ) ;
267- let var_id = tracer. ensure_variable_id ( name) ;
281+ recorder . tracer . register_variable_with_full_value ( name, val_rec. clone ( ) ) ;
282+ let var_id = recorder . tracer . ensure_variable_id ( name) ;
268283 result. push ( FullValueRecord { variable_id : var_id, value : val_rec } ) ;
269284 }
270285 }
@@ -309,7 +324,7 @@ unsafe extern "C" fn record_event_api(self_val: VALUE, path: VALUE, line: VALUE,
309324 String :: from_utf8_lossy ( std:: slice:: from_raw_parts ( ptr as * const u8 , len) ) . to_string ( )
310325 } ;
311326 let line_num = rb_num2long ( line) as i64 ;
312- let content_str = value_to_string ( content) . unwrap_or_default ( ) ;
327+ let content_str = value_to_string ( content, recorder . to_s_id ) . unwrap_or_default ( ) ;
313328 record_event ( & mut recorder. tracer , & path_str, line_num, & content_str) ;
314329 rb_sys:: Qnil . into ( )
315330}
@@ -350,29 +365,28 @@ unsafe extern "C" fn event_hook_raw(data: VALUE, arg: *mut rb_trace_arg_t) {
350365 let binding = rb_tracearg_binding ( arg) ;
351366 recorder. tracer . register_step ( Path :: new ( & path) , Line ( line) ) ;
352367 if !NIL_P ( binding) {
353- record_variables ( & mut recorder. tracer , binding) ;
368+ record_variables ( recorder, binding) ;
354369 }
355370 } else if ( ev & RUBY_EVENT_CALL ) != 0 {
356371 let binding = rb_tracearg_binding ( arg) ;
357372
358373 let self_val = rb_tracearg_self ( arg) ;
359374 let mid_sym = rb_tracearg_callee_id ( arg) ;
360375 let mid = rb_sym2id ( mid_sym) ;
361- let class_id = rb_intern ( b"class\0 " . as_ptr ( ) as * const c_char ) ;
362- let defined_class = rb_funcall ( self_val, class_id, 0 ) ;
376+ let defined_class = rb_funcall ( self_val, recorder. class_id , 0 ) ;
363377 if !NIL_P ( binding) {
364378 // register parameter types first
365- let _ = record_parameters ( & mut recorder. tracer , binding, defined_class, mid, false ) ;
379+ let _ = record_parameters ( recorder, binding, defined_class, mid, false ) ;
366380 }
367- let self_rec = to_value ( & mut recorder. tracer , self_val, 10 ) ;
381+ let self_rec = to_value ( & mut recorder. tracer , self_val, 10 , recorder . to_s_id ) ;
368382 recorder
369383 . tracer
370384 . register_variable_with_full_value ( "self" , self_rec. clone ( ) ) ;
371385
372386 let mut args = if NIL_P ( binding) {
373387 vec ! [ ]
374388 } else {
375- record_parameters ( & mut recorder. tracer , binding, defined_class, mid, true )
389+ record_parameters ( recorder, binding, defined_class, mid, true )
376390 } ;
377391 args. insert ( 0 , recorder. tracer . arg ( "self" , self_rec) ) ;
378392 recorder. tracer . register_step ( Path :: new ( & path) , Line ( line) ) ;
@@ -391,12 +405,12 @@ unsafe extern "C" fn event_hook_raw(data: VALUE, arg: *mut rb_trace_arg_t) {
391405 } else if ( ev & RUBY_EVENT_RETURN ) != 0 {
392406 recorder. tracer . register_step ( Path :: new ( & path) , Line ( line) ) ;
393407 let ret = rb_tracearg_return_value ( arg) ;
394- let val_rec = to_value ( & mut recorder. tracer , ret, 10 ) ;
408+ let val_rec = to_value ( & mut recorder. tracer , ret, 10 , recorder . to_s_id ) ;
395409 recorder. tracer . register_variable_with_full_value ( "<return_value>" , val_rec. clone ( ) ) ;
396410 recorder. tracer . events . push ( TraceLowLevelEvent :: Return ( ReturnRecord { return_value : val_rec } ) ) ;
397411 } else if ( ev & RUBY_EVENT_RAISE ) != 0 {
398412 let exc = rb_tracearg_raised_exception ( arg) ;
399- if let Some ( msg) = value_to_string ( exc) {
413+ if let Some ( msg) = value_to_string ( exc, recorder . to_s_id ) {
400414 recorder. tracer . events . push ( TraceLowLevelEvent :: Event ( RecordEvent {
401415 kind : EventLogKind :: Error ,
402416 metadata : String :: new ( ) ,
0 commit comments